Knowledge Base

Protecting against Server Side Request Forgery (SSRF)

What is SSRF?

Server-side request forgery (SSRF) vulnerabilities let an attacker send crafted requests from the back-end server of a vulnerable web application. Criminals usually use SSRF attacks to target internal systems that are behind firewalls and are not accessible from the external network.

SSRF vulnerabilities occur when an attacker has full or partial control of the request sent by the backend application. SSRF is not limited to the HTTP protocol. Generally the input that the attacker controls is HTTP, but the backend request could use different protocols.

Attack illustration

You can practice attacking a vulnerable application and learn about mitigations in this interactive lesson from Snyk.

Why SSRF attacks are relevant to the Neo4j ecosystem

Neo4j is a graph database that is used to analyse data. To enable the users easy onboarding of the existing data, we have to provide ways to load files (typically CSV files) locally or from the network via http. With that functionality comes the ability of a potentially malicious user to manipulate the initial request - step one of SSRF.

How to protect my environment

Given that SSRF is an OWASP Top 10 issue, OWASP has a comprehensive guide to prevention and mitigation.

The use case "users should be able to load the data from anywhere on the internet" falls into Case 2, which is more complex to defend against.

But with a defence in depth approach, it is possible.

Neo4j does input validation as much as possible, which is your application layer defence. And if you build custom applications on top of Neo4j, it’s a good idea to limit the ability to upload data and to run raw Cypher queries to your authenticated users. But to ensure defence in depth, you should do more on the network layer.

The detection and prevention are highly specific to your infrastructure and network environment.

Running on AWS cloud

Use IMDSv2.

Running on Google cloud

Google has advisories for preventing access to metadata, Compute Engine resources and how to utilize workload identity to minimize access.

Generic mitigation

Segment your network and configure your firewall to prevent access from Neo4j to the metadata subnet (if running on cloud) and any other sensitive backend subnets. In most cases you want to prevent access to internal IP addresses originating from the backend service in general.

Configuration option

In addition to the external network-level restriction mechanisms listed above, Neo4j has an internal control mechanism which allows users to provide IP address ranges for the DBMS to block. This control is activated via a configuration setting which must be added to neo4j.conf and requires restarting the DBMS to be applied.

unsupported.dbms.cypher_ip_blocklist

Description

IP address ranges used by the DBMS to block IP requests

Valid values

Comma separated list of IPv4 and IPv6 CIDR-notation IP ranges

Default value

When the DBMS attempts to make an IP request to a URL, after resolving the URL to an IP address, it ensures this address doesn’t collide with any of the blocked IP ranges provided by the configuration setting. Because the control mechanism is applied at the IP network level, it will be applied to any HTTP and FTP requests made by Cypher features such as LOAD CSV.

There are several helpful resources one could use to help calculate their required blocklist. One such resource is ipaddressguide.com which has calculators for both IPv4 CIDR and IPv6 CIDR ranges.

Use cases

This section includes some example to help illustrate how the setting can be used in practice.

unsupported.dbms.cypher_ip_blocklist=

Blocks no traffic (default behaviour).

unsupported.dbms.cypher_ip_blocklist=0.0.0.0/0,::/0

Blocks all IPv4 and IPv6 network traffic.

unsupported.dbms.cypher_ip_blocklist=10.0.0.0/8,ff:f::/64

Blocks IPv4 traffic between 10.0.0.0 and 10.255.255.255.
Blocks IPv6 traffic between ff:f:0:0:0:0:0:0 and ff:f:0:0:ffff:ffff:ffff:ffff.

unsupported.dbms.cypher_ip_blocklist=10.0.0.0/8,10.0.0.0/24

Blocks IPv4 traffic between 10.0.0.0 and 10.255.255.255.
Blocks IPv4 traffic between 255.0.0.0 and 255.0.0.255.
Blocks no IPv6 traffic.

Supported Versions

In Neo4j, the setting is available from versions 4.4.4, 4.3.17, 4.2.19, 4.1.12, and 3.5.35.

In APOC, the setting is available from versions 4.4.0.3, 4.3.0.8, 4.2.0.12, 4.1.0.12, and 3.5.0.20.

Although the name will change to internal.dbms.cypher_ip_blocklist, the setting will also be supported in the upcoming 5.0 releases for both Neo4j and APOC.