Exploiting SSRF

Exploiting SSRF

Server-Side Request Forgery

Intro

Server-Side Request Forgery (SSRF) is a vulnerability that takes place when an application retrieves remote resources without validating user input. An attacker can supply their own input, in the form of a URL, to control the remote resources that are retrieved by the targeted server. When you have control over what resources a server requests then you can gain access to sensitive data or worse completely compromise a vulnerable host. SSRF is number 10 on the 2021 OWASP Top 10 list and is a growing threat to APIs.

SSRF Impact

The impact of this vulnerability is that an attacker would be able to leverage the target server to perform and process requests that they supply. The attacker could supply URLs that expose private data, scan the target's internal network, or compromise the target through remote code execution. Note that bug bounties payouts for SSRF are driven based on the impact that can be demonstrated with a proof of concept. In other words, make sure to experiment with your SSRF findings and see what can be compromised with them.

To drive the point home check out the bug bounty rewards for SSRF guidelines on Facebook (https://m.facebook.com/whitehat/payout_guidelines/ssrf/):

Payouts

  • $40,000 - SSRF in production and reading the response (must include canary in your report)

  • $30,000 - Blind SSRF in production and not reading the response (must trigger the canary alert)

  • $10,000 - Hitting arbitrary endpoints within a corporate network (e.g. through an unpatched CVE on a third-party system)

  • $1,000 - If you can only hit a small number of endpoints within the corporate network (e.g. a small set of hosts or loopback only)

As you can see, the more that you can do with an SSRF finding, the greater the impact and the higher the reward.

Types of SSRF

There are two types of SSRF vulnerabilities, In-Band SSRF and Blind SSRF. In Band SSRF, means that the server responds with the resources specified by the end user. If the attacker specifies the payload as http://google.com to a server with an In-Band SSRF vulnerability the server would make the request and respond to the attacker with information served from google.com. Blind SSRF takes place when the attacker supplies a URL and the server makes the request but does not send information from the specified URL back to the attacker. In the case of Blind SSRF, you would need a web server that will capture the request from the target to prove that you forced the server to make the request.

In-Band SSRF Example

For an In-Band SSRF, a URL is specified as an attack. The request is sent and the content of your supplied URL is displayed back to you in a response.

Intercepted Request:

POST api/v1/store/products

headers…

{

"inventory":"http://store.com/api/v3/inventory/item/12345"

}

Attack:

POST api/v1/store/products

headers…

{

"inventory":"§http://localhost/secrets§"

}

Response:

HTTP/1.1 200 OK headers... {

"secret_token":"crapi-admin"

}

Once you have discovered an In-Band SSRF vulnerability you could leverage control over the URL to scan the internal network environment, gather sensitive information from the localhost, or attempt to perform a remote code execution attack.

Blind SSRF Example

Blind (or Out of Band) SSRF takes place when a vulnerable server performs a request from user input but does not send a response back to the user indicating a successful attack. The app does not provide an unusual response to the user, but the server does make the request to the URL specified by the attacker. In this case, to know if the request was made you will need to have some control over the web server that is specified in the attack.

Intercepted Request:

POST api/v1/store/products

headers…

{

"inventory":"http://store.com/api/v3/inventory/item/12345"

}

Attack:

POST api/v1/store/products

headers…

{

"inventory:"§http://localhost/secrets§"

}

Response:

HTTP/1.1 200 OK headers... {}

In this case, the response is returned and we do not have any indication that the server is vulnerable. Instead of http://localhost/secrets, we will need to provide the URL to a web server that will let us see if a request is actually made. Burp Suite Pro has a great tool called Burp Suite Collaborator. Collaborator can be leveraged to set up a web server that will provide us with the details of any requests that are made to our random URL. To stick with free tools, we will leverage http://webhook.site. You can also use one of these other free sites:

By navigating to webhook.site a random URL will be created. You can then use that randomized URL as a payload and track it to see if any requests are made to it. So, our Blind SSRF attack would look more like this.

Attack:

POST api/v1/store/products

headers…

{

"inventory":"§https://webhook.site/306b30f8-2c9e-4e5d-934d-48426d03f5c0§"

}

Once we submit this request we will not depend on the response, instead, we will check webhook.site for any new requests.

I chose to demonstrate SSRF using webhook.site because it is free, does not require an account, and allows you to create custom responses. You can use the edit button (top right) to create your own custom response.

In the response body, I have emulated what could be a web server that could be a part of the crAPI architecture. This URL can be leveraged for both In-Band and Blind SSRF attacks.

Now that we have reviewed typical SSRF attacks, you will need to know the types of requests to look for when searching for vulnerabilities.

Ingredients for SSRF

When targeting an API for SSRF vulnerabilities, you will want to look for requests that have any of the following:

  • Include full URLs in the POST body or parameters

  • Include URL paths (or partial URLs) in the POST body or parameters

  • Headers that include URLs like Referer

  • Allows for user input that may result in a server retrieving resources

Let's search the crAPI collection for potential targets. When reviewing the collection we can see three potential requests that involve URLs.

  • POST /community/api/v2/community/posts

  • POST /workshop/api/shop/orders/return_order?order_id=4000

  • POST workshop/api/merchant/contact_mechanic

These three requests each allow for user input that might be processed and some include Referer headers. The community forum post allows for any authorized user to submit a title and post to the community board. It might be a stretch, but perhaps there is some content filter involved that would submit a request to any provided URL. The return_order and contact_mechanic requests both involve URLs in some way. The return_order request doesn't seem like an obvious choice, however, the response includes a URL. Testing this request will include trying to manipulate the URL that is sent in the response. Finally, the contact_mechanic request seems like the most obvious request, because the captured request contains a URL for the "Mechanic API".

Testing for SSRF

  1. Either using Postman or the web browser, proxy the requests that you are targeting to Burp Suite.

  2. Next, send the request over to Repeater to get an idea of a typical response.

  3. In the case of the return_order request, we are able to return an item once. If we attempt to return the item twice then we will receive a response that the item has already been returned.

  4. In order to successfully test this request we will need a valid order_id. So, we will need to purchase several items in order to be able to make several requests to return an item. Use the POST /workshop/api/shop/orders request to purchase several items. If you need to increase your account balance, return to the Mass Assignment exploit. Purchase enough items, so that you can attempt several attacks.

  5. To test this successfully we will need to change the attack type to Pitchfork. Note that Pitchfork allows us to pair separate payloads together. In the case of this request, we will want to pair a valid order_id with an SSRF payload. This will allow us to increase the item_id while simultaneously sending over various attack attempts.

  6. Set the first payload to valid order_id numbers. Set the second payload to potentially interesting URLs including your webhook.site URL. For additional SSRF payload ideas check out PayloadAllTheThings SSRF List.

  7. Review the results. Look for anomalies and any indication within the response that indicate that we were able to control the remote resources processed by the server. In this case, there is no indication in the response. Next, make sure to check the webhook.site and see if a blind SSRF attack was successful. Again, the URL was not requested and this request does not appear to be vulnerable. Notice the requests shows 0/500 and the message "Waiting for first request...".

Let's try this out on the contact_mechanic request. Set the attack position, copy and paste the payloads you previously used for URLs, and send the attack. Review the results and see if there is anything interesting.

Sure enough, the localhost requests fail, but the other URLs provided are successful. As far as reviewing for anomalies, we can see that there are a variety of status codes and response lengths. Upon reviewing the responses from the successful requests, we can see that the remote resources we requested were sent back over the API request.

We can also verify that a request was made from the server by visiting our webhook.site page.

Congratulations, you have successfully exploited an SSRF vulnerability! If we return back to the Facebook SSRF bounty guideline, this would be an instance where the SSRF is in production, the response is sent back to us, and we have evidence of the request being made to the web server. In other words, maximum rewards!

Last updated