CORS misconfig that worths USD200

This bug was founded in a private program. So, this post would not disclose any information about the target. In order to not giving out anything about the target, all endpoints, parameters, token names mentioned in this post are made up. This post would name the target as redacted.com.

The bug allows attacker to take advantage of CORS misconfig to steal a token from victim. So, attacker can use that token to utilize unauthorized service of the target on behalf of victim.

Background

I have been working on this target for almost a week. I have tested most of the request and response but nothing much seem interesting to me. So, I have re-checked all request and response in Burpsuite, and I realized one of the request as below is vulnerable to CORS:

GET /token HTTP/1.1
Host: subdomain.redacted.com
Origin: www.redacted.com
Connection: close
Accept: */*
Cookies: some-Cookies=xxxxxxxxxxxx;

And response is like below:

{"some_token":"xxxxxxxxxxxxxxxxxxxxxx"}

This endpoint gives 200 response even I change the Origin header to www.evil.com. So, attacker would able to steal victim’s token. However, if I just report this as a bug, it is most likely to be closed as NA. So, I need to figure out what this token is and how this can be used to create real impact to the target.

The Escalation

So, I have spent hours in searching js files, web app, request/response history regarding the name of token, the subdomain name etc. Finally, I found a JS file that related to tokens generated in the web app and a JSON like below is founded in the file:

{"unique_service":"subdomain.redacted.com"}

So, I guess the token must linked to the “unique_service” mentioned here. I spent some times read through the documentation of the target and I found that the unique_service has a utilization limit. Users need to pay for any usage of that service in excess of their free limit. The service can be reach via subdomain2.redacted.com/service. The token provided is act as authorization token in the request like below:

POST /service HTTP/1.1
Host: subdomain2.redacted.com
Authorization: Bearer <some_token>

Also I found that subdomain2 only checks the authorization token but not session of the user. So, if attacker can steal the token, they can use the service on behalf of user and consume all their free limit of the web app.

The Exploit

To exploit, attacker can simply put the following script into a website I host.

<html> 
<body>
<script>history.pushState('', '', '/')</script>
<form action="https://subdomain.redacted.com/token">
<input type="submit" value="Submit request" />
</form>
</body>
</html>

Let’s say my website is evil.com, attacker can simply trick the victim to click on evil.com in the same browser as redacted.com with proper login session. Then, evil.com would send request to https://subdomain.redacted.com/token to ask for the token. As victim is login in the same browser, its session cookies would be sent for verification as well. As the target does not check the origin of the request, it would return the token to evil.com. Then, attacker can use the token to consume victim’s free limit of the service.

The Result

I have quickly made a POC and report this bug to the target. This bug was quickly fixed by the company within days and awarded me USD200 for the subject bug.

Takeaway from this bug is if you get stucked, try investigate every single request/response again. Try understand purpose for each token/parameter, spend some times to understand the logic of the web app. Also, reading the target’s doc would always be helpful to have a better understanding of the target.

Hope you guys enjoy the read. See you next time.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store