€150 Bounty: Chaining Vulns to fully Exploit CORS Misconfiguration
Introduction
The program comprised several subdomains. Following a straightforward reconnaissance using subfinder, httpx, and Aquatone, a specific target stood out in the Aquatone report. This particular target featured a login distinct from the main application within the scope.
Upon analyzing the target, I uncovered multiple vulnerabilities, including:
1. URL Information Leak
2. CORS Misconfiguration
3. Exposed Credentials
By chaining these three vulnerabilities together, I successfully executed a one-click Account Takeover, seizing control of the victim’s session tokens.
To uphold confidentiality, the term “target” will be employed to conceal the actual company’s identity.
Walk-through
The attack is chained with 3 steps/stages/phases.
Getting authorize_session_id
When a GET request is made to https://auth.target.com/login, the response or the redirect sets the value for the URL parameter authorize_session_id to https://auth.target.com/login?authorize_session_id=<auth_session_id>.
(Note: .withCredentials() was set to true for this XMLHttpRequest.)
Getting the code
After obtaining the auth_session_id, the value is passed to another endpoint to get the code.
Two values, auth_session_id and client_id, are required to get the code. The client_id value (5952XXXXXXXXe0aa) remained static regardless of the network, session, region, device, and can be used to generate the code for anyone.
Both the client_id and auth_session_id are given to the following URL, and the result would be:
https://auth.target.com/authorize?client_id=5952XXXXXXXXe0aa&redirect_uri=https%3A%2F%2Ftechnical.prod.cloud.target.co%2Foauth&response_type=code&authorize_session_id=<auth_session_id>
The redirect or response will have the code in the URL as
https://technical.prod.cloud.target.co/oauth?code=<code>
(Note: .withCredentials() was not set for this XMLHttpRequest.)
Getting the session tokens
Once the code is obtained, a final request is made to get the session tokens.
Again, two parameters are required to complete this attack:
1. code
2. Authorization header
The code obtained from the previous attack must be fed into the following URL:
https://auth.prod.cloud.target.co/token?code=<tkncode>&grant_type=authorization_code&redirect_uri=https%3A%2F%2Ftechnical.prod.cloud.target.co%2Foauth
When this XMLHttpRequest is made, a header is required to be set:
req.setRequestHeader('Authorization', 'Basic NTk1MjNXXXXXXXXXXXXkNWNjYzdjYjEzOA==');
Like the client_id in the previously mentioned attack, this credential (NTk1MjNXXXXXXXXXXXXkNWNjYzdjYjEzOA==) was static as well. This string was base64 encoded with the `client_id` and another unknown identifier.
When the request is successfully made, the response will hold the access_token and refresh_token for controlling a victim’s session.
(Note: `.withCredentials` was set to true for this XMLHttpRequest.)
Takeaway
This process was automated with a custom CORS exploit script that can be found (here) (a very sloppy version).
The script required a lot of tweaking, and it was made recursive because this attack will work only when the victim has the attack script already opened and running in the background while the victim is logging in.
The target application only had a working authentication app and nothing past the end of the authentication process (like a dashboard, settings, profile). It was just blank and required the company’s credentials to operate further.
Timeline
Reported — November 24th, 2021
Triaged — November 29th, 2021
Bounty Awarded — December 2th, 2021
Follow me on Twitter: 124v3n012
Buy me a coffee: https://www.buymeacoffee.com/r4v3n0r