Hey Hackers. It’s been a year since I published my last blog. But here I am with a story of JS file worth $2000
I was working on this target for a while and I had found several vulnerabilities which were reported and paid. Let’s call this company target.com and the asset I was testing, connect.target.com. The parent company target.com has acquired this entity api.previous.com and is now named as connect.target.com.
Let’s simplify it:
Target.com is the parent company
api.previous.com is the entity being acquired by target.com
connect.target.com is the new name of api.previous.com (used as CNAME)
When you “dig connect.target.com”, it shows api.previous.com in the CNAME.
The 🐞 1:
I have searched for connect.target.com in the wayback archive several times. I have read all the available JS files and retrieved URLs but nothing seems juicy enough. At this moment there was nothing to look for and after several days I planned to change my target. Then I got an idea of why not to check the CNAME record in the web archive. I quickly ran a wayback url on api.previous.com which is the CNAME record of connect.target.com.
It fetched numerous URLs and JS files and started analysing them. After several hours, I found a heavy JS file like this:
The file was too large to analyze manually, so I started searching for relevant functionality instead. I came across this functionality like PUT /api/v1/campaigns/action/cancel?campaign_id=768653 HTTP/2. I quickly checked out the functionality from a normal account and it was actually an API endpoint which is used to cancel the campaign you created.
Now, as usual I tried to cancel someone else’s campaign by altering the campaign_id=768653 but it was properly protected and validate. One couldn’t harm other customers. But wait a minute!! I saw something there at the HTTP Response in repeater. It seems like the metadata of an account this campaign ID belongs to. After studying for a while, I found that that the endpoint was properly validated and one couldn’t cancel other customers’ campaigns but this endpoint was leaking some meta data of other customer accounts. All you need to change the camaign_id= and the endpoint PUT /api/v1/campaigns/action/cancel?campaign_id=768653 HTTP/2 will leak the data of the customer, the campaign_id belongs to.
The leak data of the customers, the campain_id belongs to consist of:
This meta data was not that much sensitive and probably would have got medium severity. I need to find a way to escalate the severity. Then I remembered that in this program the IDOR is out of scope and the reason is: IDORs having unguessable/non-enumerable identifiers are out of scope: As the account IDs are unguessable so it wasn’t exploitable and that’s why it was marked as out of scope. The only way to exploit IDOR was to leak UID and GUID somewhere in the response.
Got it? Yes. The meta data which were leaking at PUT /api/v1/campaigns/action/cancel?campaign_id=768653 HTTP/2 consist of AccountUid. As I have the AccountIDs now, I can exploit IDOR now. All I need is to find areas and functionalities where GUID or AccountID is being used. I quickly found two functionalities and after testing they were vulnerable to IDOR. The functionalities with IDOR could:
1: An attacker can change any users permission from user to admin
2: A attacker can update the profile information of other customers.
I added the IDOR in the report to show the impact of the meta data. And escalating the meta data leakage into IDOR led the report into high severity and I was paid $777.
The 🐞 2:
I start digging down the JS file for further functionalities and features. There were many endpoints and functionalities which were redacted in the current connect.target.com. Anyhow I was searching and testing at the same time. And at one nice moment I came across this /api/v1/api-keys/”+a.ApiKey,method:”PUT”,body:a}) in the JS file. This endpoint was for updating information about your API Key i.e name. I sent a PUT request to /api/v1/api-keys/[api-keyID] and it updated my API key information. I tried updating someone else’s API information by altering the api-keyID i.e /api/v1/api-keys/[Victim-apiKeyID] but in vain. It was properly handled and 404 was returned. I change the request method to “GET” like GET /api/v1/api-keys/45432 to see what it retrieves.
To my surprise, it rendered the victim API key. Like Seriously ? I asked myself. I couldn’t believe it for a while. I tried again by putting my another account api-keyID and it rendered that account API Keys as well.
The attacker can just run the intruder on api-keyID and it will keep rendering all the customers API keys of that ID. I immediately reported it and the program very well and responsibly handled it and deployed the fix within three hours. This was probably the easiest bug I ever came across. The vulnerability was treated as critical I was paid my most-liked figure $1337
Don’t ignore JS files. Search for different functionalities and features. Play around it and you will get a result.
Everytime you hack on an old target, you will have this instinct that this application, this endpoint, this API or this feature would have been tested by many other hackers and we skip it often. But don’t listen to your instinct here. Being a hacker you must try things which may not work. Give it a try and sometimes you will find yourself a critical bug.
Let’s get in touch on twitter: @adnanmalikinfo