Server-side request forgery, also known as SSRF, is the process of altering requests sent by the web server. Any susceptible request can be manipulated to send information to and from restricted internal systems. This type of attack is typically used to retrieve sensitive content from the internal network.
Let’s give an example, say we have an online shop, this shop has a website with a stock check feature. When a user checks to see if the website has an item in stock it sends a request to a stock management system, this system is located on the local network and so is not reachable to the wider internet. Although the user cannot directly access the stock management system, they can make requests through the website, as the request is coming from a trusted source on the same network it has no trouble reaching the stock management system.
If sufficient checks have not been implemented then the resource which is requested could be altered allowing for restricted system access. On occasion, this could also be abused to read local website file contents.
A simple example of SSRF
POST /item/check 200 HTTP/1.1
Host: jessies-bookstore.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0
Server: Apache
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
request=http://198.162.0.32:5050/check%253Fid%253D21%2526location%253DRosyth%253Dthe-hobbit
In the example above we have a POST request. This request takes a singular parameter request. This parameter appears to have a local IP address as the value. As this IP is not accessible to the wider internet we would either need to be on that same network or have the website make the request for us. In this instance, if successful it would return the stock count for the particular item.
It’s common for servers to have multiple services running, some of these services may only be accessible when on the network. However, since that network is out of reach a port scan would be unsuccessful. To get around this, it would be possible to automate multiple requests while altering the port.
POST /item/check 200 HTTP/1.1
Host: jessies-bookstore.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0
Server: Apache
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
request=http://198.162.0.32:8080/
Furthermore, as the application is designed to return the stock count result this would also allow for attackers to see the response of any requests. The above example shows that a request was made to port 8080, this was found to host a server management application, the response for which can be seen below.
HTTP/1.1 200 OK
Date: Sun, 14 Jan 2024 20:55:12 GMT
Server: Apache
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
<!doctype html>
<html>
<head>
<title>Server Management</title>
...
Reading Arbitrary Files
On occasion, there will be no additional services running on the target server. This doesn’t mean that SSRF is a dead end. By making use of the file:// schema it’ll may be possible for arbitrary file read. The example below shows that rather than requesting a network resource, the web page is requesting the /etc/passwd file.
POST /item/check 200 HTTP/1.1
Host: jessies-bookstore.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0
Server: Apache
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
request=file:///etc/passwd
Protecting against SSRF
Server-Side Request Forgery occurs when the web application does not have correct controls in place to specify what access should be granted. Let’s take the first example, one method which could be implemented to ensure that only authorised resources are requested would be to use regular expressions. I have provided a simple PHP example below, if the URL is not an exact match then it will not proceed and the request will not be made.
if(preg_match('/^https:\/\/192\.168\.0\.32:5050\/check\?id=([0-9]*?)&location=([a-zA-Z]*?)$/', $_POST['request']))
{
//make request...
}
So what happens if the web application speaks with multiple restricted systems? In situations like this, developers can make use of a whitelist. A whitelist is essentially a list of pre-approved domains or IP addresses. If the request is not specified as okay then the application will prevent any information from being sent.