What is Server Side Request Forgery (SSRF)?

Server Side Request Forgery (SSRF) refers to an attack where in an attacker is able to send a crafted request from a vulnerable web application. SSRF is usually used to target internal systems behind firewalls that are normally inaccessible to an attacker from the external network. Additionally, it’s also possible for an attacker to leverage SSRF to access services from the same server that is listening on the loopback interface (127.0.0.1).

Typically Server Side Request Forgery (SSRF) occurs when a web application is making a request, where an attacker has full or partial control of the request that is being sent. A common example is when an attacker can control all or part of the URL to which the web application makes a request to some third-party service.

SSRF

The following is an example in PHP that is vulnerable to Server Side Request Forgery (SSRF).

<?php

/**
* Check if the 'url' GET variable is set
* Example - http://localhost/?url=http://testphp.vulnweb.com/images/logo.gif
*/
if (isset($_GET['url'])){
$url = $_GET['url'];

/**
* Send a request vulnerable to SSRF since
* no validation is being done on $url
* before sending the request
*/
$image = fopen($url, 'rb');

/**
* Send the correct response headers
*/
header("Content-Type: image/png");

/**
* Dump the contents of the image
*/
fpassthru($image);
}

In the above example, since the attacker has full control of the url parameter, in addition to being able to make arbitrary GET requests to any website on the Internet. An attacker can also make requests to resources on the server.

For example, it’s possible for an attacker to access services on localhost. In the following example, an attacker can make the following request on Apache HTTP Servers with mod_status enabled (enabled by default).

GET /?url=http://localhost/server-status HTTP/1.1
Host: example.com

Similarly, Server Side Request Forgery (SSRF) can be used to make requests to other internal resources which the web server has access to, but are not publicly facing. Such an example would be accessing instance metadata in Amazon EC2 and OpenStack instances. This service is only available to the server and not to the outside world. An attacker can even get creative with SSRF and run port scans on internal networks with this approach.

GET /?url=http://169.254.169.254/latest/meta-data/ HTTP/1.1
Host: example.com

Apart from the http:// and https:// URL schemas, an attacker may take advantage of lesser-known or legacy URL schemas to access files on the local system or on the internal network.

An example of such a request is the following using the file:/// URL schema.

GET /?url=file:///etc/passwd HTTP/1.1
Host: example.com

Depending on how the application is making the request, URL schemas other than file and HTTP could be available to the attacker to use. For example, if cURL were being used to make requests (the example above makes use of fopen() to make requests) it’s possible to use the dict URL schema to make requests to any host on any port and send custom data.

GET /?url=dict://localhost:11211/stat HTTP/1.1
Host: example.com

The above request will cause the application to connect to localhost on port 11211 and send the string “stat”. Port 11211 is the default port used by Memcached, which is not normally exposed. For a comprehensive list of attacks and URL schemas that can be used, ONSec Labs maintain a detailed document with a lot of useful information about Server Side Request Forgery (SSRF) attacks.

Detecting Server Side Request Forgery (SSRF)

In order to detect Server Side Request Forgery (SSRF) automatically, we’ll need to rely on an intermediary service since the detection of such a vulnerability requires an out-of-band and time-delay vector. Acunetix solves this by making use of AcuMonitor as its intermediary service during an automated scan.

During a scan, Acunetix will make requests containing a unique AcuMonitor URL. If AcuMonitor receives a request on one of these unique URLs, it will send a notification back to Acunetix indicating it should raise an alert for Server Side Request Forgery (SSRF).

The following is the result of an Acunetix scan with AcuMonitor to detect Server Side Request Forgery (SSRF). The alert contains information about the HTTP request that was performed including the IP address of the server that made this request and the User-agent string used in the request, if any. This information can help the developers identify the source of the problem and fix it.

SSRF

Mitigating Server Side Request Forgery (SSRF)

Whitelists and DNS resolution

Implementing simple blacklists or regular expressions directly on the user’s input to filter out which IP addresses or domains can make requests is a bad approach to take when mitigating an SSRF.

In general, blacklists are a poor security control because there will always be bypasses not envisaged by a developer. In this case, bypass by an attacker are as easy as using an HTTP redirect, a wildcard DNS service such as xip.io or even alternate IP encoding.

Instead, the most robust way of dealing with Server Side Request Forgery (SSRF) is to whitelist the DNS name or IP address which your application needs access to. If a whitelist approach does not suit your use case, and you must rely on a blacklist, it’s important to validate user input properly. An example of this is to not allow requests to private (“non-routable”) IP addresses (detailed in RFC 1918), however, in the case of a blacklist, the correct mitigation to adopt will vary from application to application. In other words, there is no universal “fix” to SSRF since it highly depends on the application’s functionality and business requirements.

Response handling

Ensuring that the response received by the remote server is indeed what the server is expecting is important to prevent any unforeseen response data leaking to the attacker. Above all else, under no circumstances should the raw response body from the request sent by the server be delivered to the client.

Disable unused URL schemas

If your application only makes use of HTTP or HTTPS to make requests, only allow those URL schemas. Disabling unused URL schemas will prevent a web application from making requests using potentially dangerous URL schemas such as file:///, dict://, ftp:// and gopher://.

Authentication on internal services

Services such as Memcached, Redis, Elasticsearch and MongoDB do not require authentication by default. Server Side Request Forgery vulnerabilities could provide an attacker with the opportunity to access some of these services without any authentication standing in the way. Therefore, it’s best to enable authentication wherever possible as another defense mechanism.

Share this post

Leave a Reply

Your email address will not be published.