27.1. Securing Neo4j Server

Secure the port and remote client connection accepts

By default, the Neo4j Server is bundled with a Web server that binds to host localhost on port 7474, answering only requests from the local machine.

This is configured in neo4j.conf:

# Let the webserver only listen on the specified IP. Default is localhost (only
# accept local connections). Uncomment to allow any connection.
dbms.connector.http.type=HTTP
dbms.connector.http.enabled=true
#dbms.connector.http.address=0.0.0.0:7474

If you want the server to listen to external hosts, configure the Web server in neo4j.conf by setting the property dbms.connector.http.address=0.0.0.0:7474 which will cause the server to bind to all available network interfaces. Note that firewalls et cetera have to be configured accordingly as well.

Server authentication and authorization

Neo4j requires clients to supply authentication credentials when accessing the REST API. Without valid credentials, access to the database will be forbidden.

The authentication and authorization data is stored under data/dbms/auth. If necessary, this file can be copied over to other neo4j instances to ensure they share the same username/password (see the section called “Copying security configuration from one instance to another”).

Please refer to Section 20.3, “REST API Authentication and Authorization” for additional details. When accessing Neo4j over unsecured networks, make sure HTTPS is configured and used for access (see the section called “HTTPS support”).

If necessary, authentication may be disabled. This will allow any client to access the database without supplying authentication credentials.

# Disable authorization
dbms.security.auth_enabled=false
[Warning]Warning

Disabling authentication is not recommended, and should only be done if the operator has a good understanding of their network security, including protection against cross-site scripting (XSS) attacks via web browsers. Developers should not disable authentication if they have a local installation using the default listening ports.

HTTPS support

The Neo4j server includes built in support for SSL encrypted communication over HTTPS. The first time the server starts, it automatically generates a self-signed SSL certificate and a private key. Because the certificate is self signed, it is not safe to rely on for production use, instead, you should provide your own key and certificate for the server to use.

[Caution]Caution

Using auto-generation of self-signed SSL certificates will not work if the Neo4j server has been configured with multiple connectors that bind to different IP addresses. If you need to use multiple IP addresses, please configure certificates manually and use multi-host or wildcard certificates instead.

To provide your own key and certificate put them in the certificates directory. The files must be named neo4j.key and neo4j.cert. The location of the directory can be configured by setting dbms.directories.certificates in neo4j.conf.

# Certificates location (auto generated if the file does not exist)
dbms.directories.certificates=certificates

Note that the key should be unencrypted. Make sure you set correct permissions on the private key, so that only the Neo4j server user can read/write it.

Neo4j also supports chained SSL certificates. This requires to have all certificates in PEM format combined in one file and the private key needs to be in DER format.

You can set what port the HTTPS connector should bind to in the same configuration file, as well as turn HTTPS on or off:

dbms.connector.https.type=HTTP
dbms.connector.https.enabled=true
dbms.connector.https.encryption=TLS
dbms.connector.https.address=localhost:7473

Arbitrary code execution

[Important]Important

The Neo4j server exposes remote scripting functionality by default that allow full access to the underlying system. Exposing your server without implementing a security layer presents a substantial security vulnerability.

By default, the Neo4j Server comes with some places where arbitrary code code execution can happen. These are the Section 20.17, “Traversals” REST endpoints. To secure these, either disable them completely by removing offending plugins from the server classpath, or secure access to these URLs through proxies or Authorization Rules. Also, the Java Security Manager, see http://docs.oracle.com/javase/7/docs/technotes/guides/security/index.html, can be used to secure parts of the codebase.

Server authorization rules

Administrators may require more fine-grained security policies in addition to the basic authorization and/or IP-level restrictions on the Web server. Neo4j server supports administrators in allowing or disallowing access the specific aspects of the database based on credentials that users or applications provide.

To facilitate domain-specific authorization policies in Neo4j Server, security rules can be implemented and registered with the server. This makes scenarios like user and role based security and authentication against external lookup services possible. See org.neo4j.server.rest.security.SecurityRule in the javadocs downloadable from Maven Central (org.neo4j.app:neo4j-server).

[Caution]Caution

The use of Server Authorization Rules may interact unexpectedly with the built-in authentication and authorization (see the section called “Server authentication and authorization”), if enabled.

Enforcing Server Authorization Rules

In this example, a (dummy) failing security rule is registered to deny access to all URIs to the server by listing the rules class in neo4j.conf:

dbms.security.http_authorization_classes=my.rules.PermanentlyFailingSecurityRule

with the rule source code of:

public class PermanentlyFailingSecurityRule implements SecurityRule
{

    public static final String REALM = "WallyWorld"; // as per RFC2617 :-)

    @Override
    public boolean isAuthorized( HttpServletRequest request )
    {
        return false; // always fails - a production implementation performs
                      // deployment-specific authorization logic here
    }

    @Override
    public String forUriPath()
    {
        return "/*";
    }

    @Override
    public String wwwAuthenticateHeader()
    {
        return SecurityFilter.basicAuthenticationResponse(REALM);
    }
}

With this rule registered, any access to the server will be denied. In a production-quality implementation the rule will likely lookup credentials/claims in a 3rd-party directory service (e.g. LDAP) or in a local database of authorized users.

Example request

  • POST http://localhost:7474/db/data/node
  • Accept: application/json; charset=UTF-8

Example response

  • 401: Unauthorized
  • WWW-Authenticate: Basic realm="WallyWorld"

Using Wildcards to Target Security Rules

In this example, a security rule is registered to deny access to all URIs to the server by listing the rule(s) class(es) in neo4j.conf. In this case, the rule is registered using a wildcard URI path (where * characters can be used to signify any part of the path). For example /users* means the rule will be bound to any resources under the /users root path. Similarly /users*type* will bind the rule to resources matching URIs like /users/fred/type/premium.

dbms.security.http_authorization_classes=my.rules.PermanentlyFailingSecurityRuleWithWildcardPath

with the rule source code of:

public String forUriPath()
{
    return "/protected/*";
}

With this rule registered, any access to URIs under /protected/ will be denied by the server. Using wildcards allows flexible targeting of security rules to arbitrary parts of the server’s API, including any unmanaged extensions or managed plugins that have been registered.

Example request

  • GET http://localhost:7474/protected/tree/starts/here/dummy/more/stuff
  • Accept: application/json

Example response

  • 401: Unauthorized
  • WWW-Authenticate: Basic realm="WallyWorld"

Using Complex Wildcards to Target Security Rules

In this example, a security rule is registered to deny access to all URIs matching a complex pattern. The config looks like this:

dbms.security.http_authorization_classes=my.rules.PermanentlyFailingSecurityRuleWithComplexWildcardPath

with the rule source code of:

public class PermanentlyFailingSecurityRuleWithComplexWildcardPath implements SecurityRule
{

    public static final String REALM = "WallyWorld"; // as per RFC2617 :-)

    @Override
    public boolean isAuthorized( HttpServletRequest request )
    {
        return false;
    }

    @Override
    public String forUriPath()
    {
        return "/protected/*/something/else/*/final/bit";
    }

    @Override
    public String wwwAuthenticateHeader()
    {
        return SecurityFilter.basicAuthenticationResponse(REALM);
    }
}

Example request

  • GET http://localhost:7474/protected/wildcard_replacement/x/y/z/something/else/more_wildcard_replacement/a/b/c/final/bit/more/stuff
  • Accept: application/json

Example response

  • 401: Unauthorized
  • WWW-Authenticate: Basic realm="WallyWorld"

Using a proxy

Although the Neo4j server has a number of security features built-in (see the above chapters), for sensitive deployments it is often sensible to front against the outside world it with a proxy like Apache mod_proxy [2].

This provides a number of advantages:

  • Control access to the Neo4j server to specific IP addresses, URL patterns and IP ranges. This can be used to make for instance only the /db/data namespace accessible to non-local clients, while the /db/admin URLs only respond to a specific IP address.

    <Proxy *>
      Order Deny,Allow
      Deny from all
      Allow from 192.168.0
    </Proxy>

    While it is possible to develop plugins using Neo4j’s SecurityRule (see above), operations professionals would often prefer to configure proxy servers such as Apache. However, it should be noted that in cases where both approaches are being used, they will work harmoniously provided that the behavior is consistent across proxy server and SecurityRule plugins.

  • Run Neo4j Server as a non-root user on a Linux/Unix system on a port < 1000 (e.g. port 80) using

    ProxyPass /neo4jdb/data http://localhost:7474/db/data
    ProxyPassReverse /neo4jdb/data http://localhost:7474/db/data
  • Simple load balancing in a clustered environment to load-balance read load using the Apache mod_proxy_balancer [3] plugin

    <Proxy balancer://mycluster>
    BalancerMember http://192.168.1.50:80
    BalancerMember http://192.168.1.51:80
    </Proxy>
    ProxyPass /test balancer://mycluster

LOAD CSV

The Cypher LOAD CSV clause can load files from the filesystem, and its default configuration allows any file on the system to be read using a file:/// URL. This presents a security vulnerability in production environments where database users should not otherwise have access to files on the system. For production deployments, configure the dbms.directories.import setting, which will make all files identified in a file:/// URL relative to the specified directory, similarly to how a unix chroot works. Alternatively, set the dbms.security.allow_csv_import_from_file_urls setting to false, which disables the use of file:/// URLs entirely. Further information can be found in Section 11.6, “Load CSV”.

Neo4j Web Interface Security

For configuration settings to consider in order to get the level of security you want to achieve, see Section 24.7, “Configuration Settings Reference”.