How I found a Critical 0-click ATO using only information from waybackurls
Hello everyone! Today, I’d like to share an interesting discovery I made recently using information obtained through waybackurls, where I managed to take control of accounts without the need for user interaction, thanks to a legacy system found in a subdomain of another country, which was initially outside the defined scope. This legacy system allowed for the forgery of JWT keys to access the main system.
The following tools were used:
waybackurls <https://github.com/tomnomnom/waybackurls>
assetfinder <https://github.com/tomnomnom/assetfinder>
One fine day, while listing subdomains within the scope of a bug bounty program using assetfinder, I noticed that it also provided subdomains from other countries, such as:
Command used: assetfinder -d target.com
Results:
target.com
*.target.com
target.com.br
target.com.py
target.com.ar
target.com.do
etc
However, the scope of other countries was not within the acceptable scope of the Bug Bounty program.
I then used waybackurls on all the subdomains and domains listed by assetfinder, and that’s when a URL caught my attention. This URL was within a domain outside the initial scope, for example:
So, I placed a random value as a parameter:
This resulted in the following HTTP request response:
HTTP/2 302 Found
Content-Type: text/html; charset=utf-8
Location: https://admin.target.com/auth?t=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkZXN0aW5hdGlvbl9wYXRoIjoiL2NoYW5nZV9wYXNzd29yZCIsImNyZWF0ZWRfYXQiOiIyMDIzLTEwLTMwIDIwOjE4OjQzIFVUQyIsImV4cCI6MTY5ODY5NzQyMywib3JpZ2luIjoic21hcnQtc2l0ZSIsInNpbmdsZV9hY2Nlc3NfdG9rZW4iOiJGVVpaIn0.2XG4lZG-rhrw54a7qB4s65ZszZnMHCtErVgz_FsMxmU
In the HTTP request response, a 302 code was generated, redirecting to the page https://admin.target.com/, which was a subdomain within the scope where the main customer access system was located. However, in this redirect, the system constructed an authentication JWT key with the passed parameter.
Upon converting the JWT key from base64 to plain text, the following information was found:
{“typ”:”JWT”,”alg”:”HS256"}{“path”:”/pwd_change”,”created_at”:”2023–10–30 20:18:43 UTC”,”exp”:1698697423,”origin”:”smart-site”,”user_token”:”FUZZ”}
The link created a valid JWT token using the information passed as a parameter within the user_token. So, I went in search of finding this user_token that could create a valid JWT token to access the system.
I noticed that in the result of Waybackurls, there was one URL somewhat similar to the one in the HTTP request response with the JWT token. It was a password reset URL with a JWT token in the parameter.
https://admin.target.com/reset_pwd?t=eyJhbGciOiJIUzI1NiJ9eyJ0b2tlbiI6IlhYWFhYIiwiY3JlYXRlZF9hdCI6IjIwMjMtMDktMTQgMTc6NTA6MTYgLTAzMDAiLCJleHAiOjE2Nzg4MzA2MTZ9AQgvUltBC0wgSgsjYWRXW9WCSg
When decoding the expired password reset JWT token, I obtained the exact information that the other URL formed, as shown below:
{“alg”:”HS256"}{“user_token”:”XXXXX”,”created_at”:”2023–09–14 17:50:16 -0300",”exp”:1678830616}/R[A L J #adW[ՂJ
And there I found a valid user_token for the system user, which is like the user’s account ID.
So, I took the user_token found within the JWT key and placed it as a parameter in the URL of the out-of-scope system, and it injected the user’s user_token and created a valid JWT key, redirecting to the account page:
URL composition:
It redirected to https://admin.target.com?auth=[VALID JWT TOKEN] -> 302 creating a valid authentication JWT key for the user.
However, it redirected to a page that no longer existed:
https://admin.target.com/page404 -> 404 not found
I removed the non-existent URL (/page404), and the system redirected to the home page logged into the user’s account.
https://admin.target.com -> 200 Logged In
Afterward, I identified the endpoint in the API that displayed all user data and managed to retrieve all the person’s information in JSON format.
Finally, I performed another search via waybackurls looking for user ‘IDs’ in the same pattern using REGEX and found a massive number of various other links with user “IDs” in various invite links such as:
https://target.com/invite?client=XXXX and so on.
Therefore, it was possible to perform an account takeover for each user account whose ID was found solely with the information from the user_token found via waybackurl.
In the end, the company acknowledged the issue as a critical severity and paid out the maximum bounty.
Thanks for reading!