OAuth client credentials. How to find and utilize them for the bug bounty

Published in Tutorials ・April 25, 2021 ・ 2 min read

OAuth client credentials grant type is a way how to OAuth application can authenticate itself. With its client_id and client_secret, the application can obtain an access token and talk to the resource server. And you can find endpoints that return data to the client. Honestly, it is one of my favorites attack vectors because it does not require any user actions, and as a result, the severity generally is High/Critical.

Methodology


  1. Find the OAuth application credentials.
  2. Obtain the access token.
  3. Test API endpoints.

How to find OAuth client credentials (client ID and secret)


Of course, the credentials can be everywhere on the target, and you should pay attention to them in the same way how you find any other keys and tokens. But in most cases, you can find them in an authentication process in mobile applications.

So, I try all authentication types in the usual path - login by email, phone number, third-party services like Google or Facebook, and logout process. Especially in mobile apps, but do not avoid other ways like web or desktop applications.

Generally, the requests that I am trying to find looks like this:

POST /login HTTP/1.1
Host: target.com
Authorization: Basic ZmM0YjVmZDY4MTZmNzVhN2M4MWZjOjZhMjk5YmQ4MDMzOTcxNjZlOGM0Y2Y5MjgwYjgwMWQ2MmM=
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Connection: close

email=attacker%40mail.com&password=oooPaSSooo

Here the client credentials encoded in base64 in format

{CLIENT_ID}:{CLIENT_SECRET}
echo "ZmM0YjVmZDY4MTZmNzVhN2M4MWZjOjZhMjk5YmQ4MDMzOTcxNjZlOGM0Y2Y5MjgwYjgwMWQ2MmM=" | base64 -d

=>
fc4b5fd6816f75a7c81fc:6a299bd803397166e8c4cf9280b801d62c

Or it passed in the request body:

POST /oauth/login HTTP/1.1
Host: target.com
Content-Type: application/json
Connection: close

{
  "email":"[email protected]",
  "password":"oooPaSSooo",
  "grant_type":"password",
  "client_id":"fc4b5fd6816f75a7c81fc",
  "client_secret":"6a299bd803397166e8c4cf9280b801d62c"
}

Additionally, If the target allows you to register your OAuth2 application - do that too.

How to utilize the OAuth client credentials


Assume we already have two pairs of credentials. One pair from the target’s some internal app and the second one - from your self-registered app.

My next step is to find an access token exchange endpoint. This step is optional, so do not stop here if you have not found any. If you have registered your application, you should find the endpoint in the API documentation for third-party developers. In other cases, look to authentication requests again. Because we have already done it, search in proxy history for the ‘grant_type’ term.

My second example authentication request already looks like a token exchange endpoint. So change the grant_type value to the client_credentials and delete extra params.

The resulted request:

POST /oauth/login HTTP/1.1
Host: target.com
Content-Type: application/json
Connection: close

{
  "grant_type":"client_credentials",
  "client_id":"fc4b5fd6816f75a7c81fc",
  "client_secret":"6a299bd803397166e8c4cf9280b801d62c"
}

Suppose I did not find the token exchange endpoint - not a big problem. I still have the client credentials that I will use as basic auth in requests. Sometimes it’s enough for the attack.

So in good scenario I have additionaly two access tokens (internal/own client). And as a result there are 4 Authorization header values:

  • Basic {base64(client1_id:client1_secret)}
  • Basic {base64(client2_id:client2_secret)}
  • Bearer {client1_access_token}
  • Bearer {client2_access_token}

Further, I use these headers like independent roles in Access Controls tests. So I utilize them in all API endpoints that I have. I especially recommend trying them on endpoints that are forbidden for a regular user or have the user’s sensitive information. GraphQL is a good target for this technique too.

References