OAuth 2.0 is an authorization framework for Web Application. It validates the identity of a user to the website which requested it without disclosing passwords to the website. This might sound complicated at first but let’s take an example: A user wants to login to a website. He heads to the signup page and finds three options to log in- Via Facebook, Via Google, Via LinkedIn. When the user clicks one of them, he authenticates himself to the website. OAuth is done so as it saves time for entering details such as Name, Address etc which are already available at some other websites such as Facebook. Also, it saves user time to manually fill the login form. The approval process is so coordinated that it takes a minimum number of steps to approve or decline resources to a user.
In this blog we are going to cover the following points:
- Working of OAuth 2.0
- Security Vulnerabilities found on OAuth 2.0
Working of OAuth 2.0
OAuth2 defines 4 roles:
- Resource Owner: The User accessing an application.
- Resource Server: Server hosting protected information or user data.
- Client: Application registered to the Provider (ex. Facebook, Google)
- Authorization Server: Server issuing access token to the client. This token will be used for the client to request the resource server. This server can be the same as the authorization server (same physical server and the same application), and it is often the case.
There is a request sent from the server when an application demands for an auth request. The request or response contains the following things:
- Redirect URI: After the OAuth flow is complete the application will redirect it to this URL. It is generally represented as redirect_uri. The server usually rejects redirect_uri if a different value is provided than that existing on the server.
- Access Token: Every application generates this secret token which is required at every request.
- Client Id: A unique identifier returned when an application is registered successfully. This parameter is not secret information but crucial in working of OAuth.
- Client Secret: A unique token which is generated after registration. It is usually tied with Client Id and is generally used to generate access tokens.
Receiving Grants
There are different types of authorization flows, some of which are:
- Authorization Grant
- Implicit Grant
Let’s have a look at them in the following sections.
Authorization Grant
When is Authorization Grant used?
Authorization grants are used if our client is a web server. It allows us to obtain a long-lived access token which can be renewed with a refresh token.
Scenario:
- A website wants to obtain information about your Facebook profile.
- You are redirected by the client (the website) to the authorization server (Facebook).
- If you authorize access, the authorization server sends an authorization code to the client (the website) in the call-back response.
- Then, this code is exchanged against an access token between the client and the authorization server.
- The website is now able to use this access token to query the resource server (Facebook) and retrieve your profile data.
Such tokens usually contain a token lifeline and a refresh token when sent from Google. These tokens are not stored in the session cookie.
An Authorization grant looks like the following:
https://gauravnarwani.com/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read
where,
- code: Authorization grant condition
- scope: Level of access needed
After permission is granted, a grant code is generated
https://gauravnarwani.com/redirect?code=a5b6h3dass
These parameters combine together to form Access Token
Access Token = Auth Code + Client Id + Client Secret + Redirect URL
The post request sent to the server will be as:
https://gauravnarwani.com//oauth/token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=authorization_code&code=AUTH_CODE&redirect_uri=CALLBACK_URL
will give the JSON response as:
{“access_token”= “a4hb6sdfg39bsdfb3287hds”}
Implicit Grants
When it should be used?
It is typically used when the client is running in a browser using a scripting language such as JavaScript. This grant type does not allow the issuance of a refresh token. It does not require an endpoint on the client to call supply-authorization code and client secret to then receive an access token.
Scenario:
- The client (AngularJS) wants to obtain information about your Facebook profile.
- You are redirected by the browser to the authorization server (Facebook).
- If you authorize access, the authorization server redirects you to the website with the access token in the URI fragment (not sent to the web server). Example of call back: http://example.com/oauthcallback#access_token=MzJmNDc3M2VjMmQzN.
- This access token can now be retrieved and used by the client (AngularJS) to query the resource server (Facebook). Example of query: https://graph.facebook.com/me?access_token=MzJmNDc3M2VjMmQzN.
The only difference between an authorization grant and an implicit grant is the response_type parameter, which is set to token. This instructs the authorization server that the type we’re going to use is implicit.
Let us see the following link for more information:
https://gauravnarwani.com/oauth/authorize?response_type=token&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read,write
When the above link is loaded, a permission prompt is popped. When the user authorizes the application, the server redirects to the URL in redirect_uri with the access token in the URL itself, preceded by a hash, similar to this:
https://gauravnarwani.com/token#access_token=ds7t8hsbdasdaksjdasdasd
The 3rd party can now communicate using this token.
Now that we have understood the basics of OAuth 2.0 let’s see the security vulnerabilities found on OAuth 2.0.
Security Vulnerabilities found on OAuth 2.0
There are many vulnerabilities one can discover on websites using OAuth, some of them are listed under.
Vulnerability in Authorization Grant
This vulnerability is very common and can be found on many websites who have misconfigured flow. It can be used to completely take over any victims account when he clicks on a URL that changes his access tokens.
Suppose we have a website https://gauravnarwani.com which is a shopping website. Let us assume this to be called Website A for more simplicity.
The user now wants to login to the application. He heads over to the login page where he finds various methods of signing in such as Facebook, Google etc.
Let us suppose the user logs in via Facebook
Working:
- The victim is allowed in the application after he connects through Facebook.
- The attacker will click the Connect Facebook button on the webpage but will not follow the redirection to website A. (The attacker can perform this via Burp Proxy or via Firefox NoRedirect addon).
- The attacker then gets the URL (with authentication code) to which he would be redirected.
- Now the attacker then forces the victim to visit this URL via a hidden iframe on a website or an image in an email for example.
- If the victim is logged in website A, jackpot! Now the attacker has access to the victim’s account in website A with his Facebook account. He just has to click on the Facebook Connect button and he will be connected with the victim’s account.
If the URL is accepted it will show 200 OK in the header of the response. The URL updates the access token of the victim to that of the attacker, so whenever the attacker logs in again via the Facebook connect, the access token points to the victims account. The attacker can entirely claim the victims account now.
Workaround:
This is prevented by adding a “state” parameter. The parameter state generally matches to a unique hash of a random number that is stored in the user session. In our example, if the website A was using the parameter “state”, he would have realized in the call back that the hash does not match the one stored in the session of the victim and would, therefore, prevent the theft of victim’s account. If the value is different than that stored in the server, the value of access token would be unchanged and would return a 302 Unchanged in the response header.
Vulnerability in Implicit Grant
This type of authorization is the least secure of all because it exposes the access token to client-side. There is a big chance that the client does not know if the access token was generated for him or not. This allows an attacker to steal a user account.
Example:
- An attacker aims to steal a victim’s account on a website A. This website allows you to connect via your Facebook account and uses implicit authorization.
- The attacker creates a website B allowing login via Facebook too.
- The victim logs in to the website B with his Facebook account and therefore implicitly authorized the generation of an access token for this.
- The attacker gets the access token via his website B and uses it on website A by modifying the access token in the URI fragment. If website A is not protected against this attack, the victim’s account is compromised and the attacker now has access to it.
Workaround:
To avoid this, the authorization server must provide in its API a way to retrieve access token information. Thus, website A would be able to compare the client_id of the access token of the attacker against its own client_id. As the stolen access token was generated for the website B, client_id would have been different from client_id of website A and the connection would have been refused.
Clickjacking
With a technique known as clickjacking, we can simply force a user to click the allow button without them recognising. The first criteria of exploiting this are that the grant prompt must be free from any framing protection, such as X-FRAME-OPTIONS header. In this attack, an attacker can hide a grant prompt page into a website which he controls by changing its opacity value. There are a series of catchy buttons which when pressed are the actions happening on the prompt. As soon as the victim presses the allow button, access tokens are granted to the attacker and its game over for the victim.
Open Redirection
As the name suggests open redirection is when an attacker redirects the victim to a malicious or a phishing site. There are various methods to perform open redirection in OAuth, we will look at some below.
Open Redirection – the malformed URL
Let us just assume the attacker has an exploit located at https://evil.com and the trusted website by OAuth is https://trusted.com. The attacker has a better chance to trick users into clicking links having www.trusted.com in its URL than directly supplying exploit link.
Let’s assume that www.trusted.com runs an OAuth 2.0 server at https://api.trusted.com and allows its users to register on OAuth 2.0 client application by filling appropriate details. The redirect_uri must be set to our exploit page.
The grant link looks like the following:
https://api.trusted.com/oauth2/authorization?response_type=code&client_id=75asdasd85sd&scope=read&redirect_uri=https://evil.com
This results in a normal prompt. Now changing the scenario to form malformed URL(changing the client_id and scope to garbage values) results in URL Redirection to our exploit page.
Malformed Value in scope:
https://api.trusted.com/oauth2/authorization?response_type=code&client_id=75asdasd85sd&scope=hahahahahahaha&redirect_uri=https://evil.com
Malformed Value in client_id:
https://api.trusted.com/oauth2/authorization?response_type=code&client_id=doesntexist&scope=read&redirect_uri=https://evil.com
As soon as they occur, the server replies back with an error message, redirecting the user to the evil URL.
Directory Traversal Tricks
Directory Traversal Tricks assumes that we can save certain files of our choice under an allowed domain, this case the web applications which allow uploading of files and so on.
The following are the URLs which can effectively bypass the validation if traversals are not considered:
https://example.com/token/callback/../../our/path
https://example.com/token/callback/.%0a./.%0d./our/path
https://example.com/token/callback/%2e%2e/%2e%2e /our/path
Visit: http://www.paulosyibelo.com/2016/06/facebooks-moves-oauth-redirecturi-bypass.html for example and POC video
Domain Tricks – TLD suffix confusion
We can bypass certain checks if a certain top-level domain is specified. We can bypass the redirect_uri with a .com TLD by replacing it with a suffix .com.mx, .com.br
Original: https://example.com/token/callback
Suffixed: https://example.com.mx/token/callback
This issue has been discovered in OAuth implementation of Instagram and Slack.
- Slack: https://hackerone.com/reports/2575
- Instagram: http://www.breaksec.com/?p=6164
Flow hijack through open redirection on client
It is easier to find an open redirect on the client and its subdomains. An attacker can use this to his advantage and by using that link, he can redirect the victim to his site.
For Example:
- Redirect link: https://example.com/exit/redirect.php?u=https://google.com
- Exploit: https://example.com/exit/redirect.php?u=https://gauravnarwani.com/token/callback
The tokens will now redirect at https://gauravnarwani.com/token/callback.
#Bug Bounty Tip – A way to bypass filter for cross-site scripting is to add a null character before your payload. IF there is character validation on certain line, this will take you to a new line where your payload will fire
For ex: if <script>alert(document.domain)</script> has its ‘<‘,’>’ and ‘/’ tags filtered, try inserting the payload %0A<script>alert(document.domain)</script>
References:
- Mastering Modern Web Penetration Testing – Prakhar Prasad
- Bubblecode Article: Understanding OAuth2 – Johann Reinke