What is server-side request forgery (SSRF) and how can you prevent it?
Server-side request forgery (SSRF) is an attack that allows attackers to send malicious requests to other systems via a vulnerable web server. Listed in the OWASP Top 10 as a major application security risk, SSRF vulnerabilities can lead to information exposure and open the way for far more dangerous attacks. This post shows how SSRF works and how you can identify and prevent SSRF vulnerabilities in your web applications.
Your Information will be kept private.
Your Information will be kept private.
Introduction to server-side request forgery (SSRF)
Web applications can trigger requests between HTTP servers. These are typically used to fetch remote resources, such as software updates, or to import metadata from a URL or another web application. Such inter-server requests are not dangerous in general, but unless implemented correctly, they can make a server vulnerable to server-side request forgery, or SSRF.
A server-side request forgery (SSRF) vulnerability is introduced when user-controllable data is used to build the target URL. To perform an SSRF attack, an attacker can then change a parameter value in the vulnerable web application to create or control requests from the vulnerable server.
External resources accessed by a web application may include internal services, for example an RSS feed from another website. A developer might use the following URL to retrieve a remote feed:
https://example.com/feed.php?url=externalsite.com/feed/to
If the attacker is able to change the url
parameter to localhost
(the loopback interface), this may allow them to view local resources hosted on the server, making it vulnerable to server-side request forgery.
If attackers can control the destination of server-side requests, this opens up a whole array of offensive activities, potentially allowing them to:
- Abuse the trust relationship between the vulnerable server and other systems
- Bypass IP whitelisting
- Bypass host-based authentication services
- Read web resources and other useful assets that are not accessible to the public, for instance metadata APIs in AWS environments or
trace.axd
in ASP.NET - Perform port scans on the internal network that the server is connected to
- Read files from the web server
- View status pages and interact with APIs as the web server
- Retrieve sensitive information such as the IP address of a web server running behind a reverse proxy
SSRF in the OWASP Top 10
Server-side request forgery is a well-known vulnerability and a regular item on the Open Web Application Security Project’s list of top ten web application security risks. In the OWASP Top 10 for 2021, it has even (for the first time) received its own category as A10:2021 – Server-Side Request Forgery (SSRF). It was included as a separate category based on the results of a community survey.
As modern web applications get more complex and interconnected, fetching a URI has become a fundamental operation for delivering content and functionality. With the rise in server-side requests, SSRF vulnerabilities have also become more common. At the same time, their scope and impact are expanding due to the growing prevalence of cloud services and intricate cloud-based application architectures, which can allow attackers to access web infrastructures and cloud data sources via a compromised server.
Typical exploitation of a server-side request forgery vulnerability
In a typical SSRF scenario, an external attacker who wants to access an internal server can’t use direct requests because they would be blocked by the firewall. Instead, malicious actors can exploit an SSRF vulnerability to make their attack via a vulnerable web server:
- The attacker sends a forged request to a web server that is vulnerable to SSRF and resides on the same internal network as the target server.
- The vulnerable web server sends the attacker-controlled request to the victim’s server, bypassing the firewall.
- The victim’s server responds to the web server with the requested data.
- If the specific SSRF vulnerability permits it, the data is sent back to the attacker. In most cases, the attacker will need to exfiltrate or infer this information by other means (out-of-band).
Why is server-side request forgery dangerous?
While many web vulnerabilities directly affect the target system, SSRF allows attackers to use the target as an intermediary that passes requests to a third system. So while an SSRF attack might not be damaging in itself, it can provide malicious hackers with access to internal systems that were never supposed to be accessible from the Internet. There are several reasons why this is dangerous.
SSRF abuses the trust relationship between internal systems
As a security best practice, you should always keep your attack surface as small as possible on all levels. In internal networks, this usually means that access to certain ports or actions is restricted to specific whitelisted machines only. To maintain security while still being able to exchange data and perform administrative tasks, servers often have a trust relationship with select other machines.
At a network level, this trust can mean that a firewall only allows access to certain ports if the requesting machine is on the same local network or if its IP address is explicitly trusted. At a software level, you can have implicit trust in local machines so that authentication is not required for some administrative tasks as long as the IP is 127.0.0.1 or perhaps inside the internal network. This adds some degree of physical security because even if an attacker obtains valid credentials, they can’t log in without access to the local network.
By exploiting an SSRF vulnerability, an attacker can circumvent such restrictions to interact with other servers that trust the affected machine. This could mean sending data queries or crafting malicious requests to interact with ports that aren’t accessible from the outside network. By forging server-side requests, an external attacker can perform malicious actions on the target server that would otherwise not be possible from the outside.
SSRF allows attackers to scan local or external networks
By exploiting a server-side request forgery vulnerability, attackers may be able to scan local or external networks that the vulnerable server is connected to. While it is usually not possible to extract data directly, attackers can use the page load time, error messages, or banners of the service they are probing to indirectly determine whether the targeted service is responding or a tested port is open.
Example: How to scan a network via an SSRF vulnerability
Imagine you have a website with a service that allows you to fetch JPEG images from a remote source so it can determine their dimensions. As a security control, the service checks if the response received from the remote source has a Content-Type
HTTP header with the value image/jpeg
. If the header is missing or specifies a different content type, the service assumes that a different image format was provided and returns the error message Please provide JPEG images only. If there is a problem connecting to the remote source, the service returns No image found!
Let’s see how attackers can use different inputs that affect the service response to determine if a host is up or not:
- If we request
https://victim.com/image.php?url=https://example.com/picture.jpg
, we get the height and width of the image, meaning that this is a valid picture with a correctContent-Type
header. - Let’s try a different HTTP request and feed the server an HTML file rather than an image by sending
https://victim.com/image.php?url=https://example.com/index.html
. Now the service response is Please provide JPEG images only, since the supplied page has the wrongContent-Type
header (text/html
instead ofimage/jpeg
). - Now let’s see what happens for an invalid URL such as
https://victim.com/image.php?url=https://example.invalid/
. The service returns Image not found, meaning there was an error fetching the remote resource.
Now that we know how the application behaves for different inputs, we can try to abuse it. We know that a valid URL with a missing or incorrect Content-Type
header returns the error Please provide jpeg images only. Let’s send the following request with an internal URL:
https://victim.com/image.php?url=127.0.0.1:3306
If we get the error Image not found, that means there is no response from host 127.0.0.1 on port 3306. However, if we get Please provide jpeg images only, it means that the internal server did respond, so there is a service running on that port. That way, we can use the vulnerable web application to probe different internal IP addresses and ports to make a complete scan. In effect, such an SSRF vulnerability allows attackers to perform port scanning without using an actual port scanner.
SSRF can expose files and internal resources on the server
When the content of a remote resource is directly rendered to a page, there is a possibility that attackers could read file content. As an example, consider a web service that removes all images from a supplied URL and then nicely formats the text. To do this, it takes the response body for a given URL and then applies text formatting.
If the service is vulnerable to SSRF and allows us to supply a file://
URL instead of the usual http://
or https://
, we can use it to read files from the local file system. For example, if we use the URL file:///etc/passwd
on a UNIX-based system, we could display the content of the passwd file. The same technique can be used to view the source code of the vulnerable web application.
What are the potential impacts of SSRF attacks?
As seen in the above examples, the direct impact of exploiting a server-side request forgery vulnerability is nearly always information disclosure because attackers obtain a lot of useful information about systems and resources that should be inaccessible to them. However, the indirect consequences can be devastating, since SSRF can allow malicious actors to:
- Use the vulnerable server as a port and IP scanner for internal and external systems
- Interact with protocols such as Gopher (if enabled) to perform additional reconnaissance
- Discover the IP addresses of servers running behind a reverse proxy
- Obtain remote code execution
Because SSRF is primarily an access channel for further probes and attacks, there are also many other possibilities, depending on how the vulnerable web application uses responses received from the remote resource. Combined with other vulnerabilities in suitable conditions, SSRF can have severe consequences.
Preventing server-side request forgery
To prevent SSRF vulnerabilities in your web applications, you are strongly advised to use a whitelist of allowed domains and protocols for remote resources fetched by the web server. More generally, you should also avoid using user input directly in any functions that can make requests on behalf of the server. While it is always a good idea to sanitize and filter user input, you should not rely on this as your sole protection because it is virtually impossible to cover all the different scenarios.
Attackers can use a wide variety of tricks to bypass URL filtering:
- Use encoded IP addresses which will be translated to an IP in an internal network:
- 1 -> same as localhost
- 123.123.123 -> same as localhost
- Supply hostnames that resolve to internal IP addresses
- Bypass host blacklisting by applying dots at the end of the hostname
This is only a small portion of bypasses that attackers have in their arsenal, so recommended practice is to avoid user input in functions that issue requests on behalf of the server.
Identifying SSRF vulnerabilities in your web applications
Modern dynamic application security testing (DAST) solutions such as Invicti provide accurate vulnerability scanning for a wide variety of web vulnerabilities, including many server-side request forgery vulnerabilities. For out-of-band SSRF and other second-order vulnerabilities, Invicti uses a dedicated vulnerability testing infrastructure that allows it to identify and report security flaws that don’t return direct responses.
Vulnerability classification and severity table
Classification | ID / Severity |
---|---|
PCI v3.2 | 6.5.6 |
OWASP 2013 | A5 |
OWASP 2017 | A6 |
OWASP 2021 | A10 (standalone category) |
CWE | 918 |
CAPEC | 347 |
WASC | 15 |
HIPAA | 164.306(a), 164.308(a) |
ISO27001 | A.14.2.5 |
CVSS:3.0 |
CVSS:3.0: AV:N/AC:H/PR:N/UI:N/S:C/C:N/I:N/A:N
|
Invicti | Critical |