POSTS
OpenID Connect: Identify Blind SSRF via Request URI Spraying
The OpenID Connect request_uri
parameter is well-known to cause blind SSRF vulnerabilities. In this post, a methodology to semi-automatically identify such issues is proposed and implemented using Burp Suite. Further, this post describes how one can programmatically obtain the Burp Suite Scope definitions for all Hackerone programs a user has access to.
In OpenID Connect 1.0, there is an optional request_uri
parameter which is intended to allow the Identity Provider (IdP) to retrieve a request object from an URI. The parameter is sent along the Auth. Request:
The request_uri Authorization Request parameter enables OpenID Connect requests to be passed by reference, rather than by value. This parameter is used identically to the request parameter, other than that the Request Object value is retrieved from the resource at the specified URL, rather than passed by value.
https://openid.net/specs/openid-connect-core-1_0.html#RequestUriParameter
In 2017, Fett et al. highlighted, that if this parameter is supported and enabled at the IdP, this allows unauthenticated blind Server-Side-Request-Forgery. Nevertheless, as for instance outlined in this post, this issue is still present in popular implementations.
Automated Discovery: Request URI Spraying using Burp Suite
This leads us to the following question: Can simply add the “request_uri” with a controlled target to all requests that look like an Auth. Request while browsing the web and just need to wait for a “hit” (i.e. an incoming request at our listener)? Spoiler: Yes, the solution is that simple, but please make sure to only apply this rule to websites in scope of a VDP or BBP!
To make sure that we only approach in-scope assets from known Bug Bounty or Vulnerability Disclosure programs, we can use the scope definitions that are published on Hackerone.
To obtain the scope for all private and public programs yu have access to, you need to perform the following steps:
- Create API token for Hackerone’s API: https://hackerone.com/settings/api_token/edit
- Run the following script as follows:
$ python3 generate_bundled_scope.py --user USERNAME --token TOKEN
Alternatively, you can enter the token via stdin:
$ python3 generate_bundled_scope.py --user USERNAME --token-stdin
The script can be found here: [TODO: Add Script to GitHub].
- The script’s output is a combined scope definition for all available programs.
Blind SSRF and Bug Bounty Programs
As we saw earlier, the described blinds SSRF issue is a quite common misconfiguration. One issue from a bug hunter’s perspective is, to proof the impact of a blind SSRF. Sometimes it may be rather difficult to even prove, that not only external, but also internal requests are possible.
This is a striking difference between a report to a random Bug Bounty Program and a pentest engagement. In a pentest engagement, the pentester may in most cases simply ask their customer if they could provide further insights on the actual impact of the SSRF vulnerability.
In a Bug Bounty context, reports on blind SSRF are - at least from my experience - often immediately closed if you only included a Proof-of-Concept for an external request being forged. But how can we actually proof the we can target the internal network?
In the past, I mostly tried to argument using a time-based port scan of localhost. But this approach was not that successful in most cases. Recently I stumbled over observable behavior that could be actually used to determine if a request to the internal network actually hit an internal system: Gateway Timeouts vs short response times on internal and link local IP addresses.
In cloud environments, the non-routable link local IP address 169.254.169.254
is to access the metadata instance.