Tl;DR;
An OAuth misconfiguration was discovered in the redirect_uri
parameter at the target’s OAuth IDP at https://app.target.com/oauth/authorize
, which allowed attackers to control the path of the callback endpoint using the ../
character. It was chained with a postMessage misconfiguration at a different subdomain https://xyz.target.com/something/somepage.html
that used the same IDP of authenticating the user which lead to access token leakage and account takever
The exploit code worked in the following way:
https://app.target.com/oauth/authorize?client_id=APP&redirect_uri=https://app.target.com/callback/../oauth/authorize%3fclient_id=XYZ%26redirect_uri=https://xyz.target.com/callback%26response_type=code%26state=%2fsomething%2fsomepage.html&response_type=token
==> 302 redirect
https://app.target.com/oauth/authorize?client_id=XYZ&redirect_uri=https://xyz.target.com/callback&response_type=code&state=/something/somepage.html#access_token=
==> 302 redirect
https://xyz.target.com/callback?code=&state=/something/somepage.html#access_token=
==> 302 redirect
https://xyz.target.com/something/somepage.html#access_token=
==> Insecure usage of postMessage sends the access_token from the hash to our malicious parent window.
For more details, continue reading the blog post 🙂
Summary
It has been a while since I last wrote about a finding. In this blog post, I wanted to share a vulnerability where I was able to chain up an OAuth misconfiguration (yes, they still exist!) with a postmessage misconfiguration that eventually allowed me to steal victim’s login tokens if they clicked on a malicious link. For the sake of confidentiality, I’ve made changes to the original vulnerable URLs.
I usually go deep into a single application while testing for bugs. It allows me to understand the functionalities of the target which can lead to findings like this one. I’ll assume that readers of this post are familiar with OAuth. If not, I strongly recommend going through this article first.
OAuth misconfiguration:
OAuth misconfigs usually happen when some properties of an OAuth client is configured insecurely and can lead to consequences like access token leakage. Let’s assume target I was testing had an OAuth IDP at
https://app.target.com/oauth/authorize
Messing with the redirect_uri
parameter is one of the most common ways to exploit a weakness where an attacker can provide a malicious URL in the redirect_uri parameter and the user would be redirected to that URL with their access_token or the OAuth code.
However, it’s become quite rare these days. Simply providing my URL in the redirect_uri
parameter didn’t work here and the server threw an error as expected. After some time, I discovered that it was possible to change the path of the callback endpoint in the redirect_uri parameter using ../
. For example, if we click:
https://app.target.com/oauth/authorize?client_id=APP&redirect_uri=https://app.target.com/callback/../anything&response_type=token
we would be redirected to: https://app.target.com/anything#access_token=
Instead of the intended /callback
endpoint!
However, this discovery was useless unless we could find an open redirection issue and chain it up with this directory traversal to exfiltate the victim’s access token. I spent some time looking for an open redirection but couldn’t find any. After spending more time, I decided to change my approach.
A different Approach
The target I was testing was a mid-sized enterprise software company with multiple subdomains and features such as resources, learning centers, blogs, etc. I began checking those out without actively testing for any bugs since all of those were out of scope.
One specific subdomain, xyz.target.com
, had a login feature that used the authorization server at https://app.target.com/oauth/authorize
, similar to the main application for authenticating a user. The OAuth call looked something like this:
https://app.target.com/oauth/authorize?client_id=XYZ&redirect_uri=https://xyz.target.com/callback&response_type=code&state=%2F
.
If the user is logged in at https://app.target.com
, the server would redirect them to: https://xyz.target.com/callback?code=
which further throws a 302 redirect with the value of the location header same as the value of state parameter, i.e. %2f (/), which means we
can control the path after the OAuth flow.
The subdomain at xyz.target.com was a learning center where users could complete their course and give exams for certifications. While surfing, I noticed an HTML file requested in the background: https://xyz.target.com/something/somepage.html
with the following content: