Now, I’m not going to sit here and pretend this writeup is the most interesting exploit in the world. It’s not about a critical vulnerability that I used to rig the NBA Championship finals. It’s simply an IDOR (Insecure Direct Object Reference). But it’s my first bug that I found out in the wild and got a bounty for, so it’s special to me.
I’m going to walk you through how I found the bug and the creative approach I managed to argue that what normally wouldn’t be a security flaw or issue with the integrity of their system, to a theoretical account takeover.
Recon
The NBA uses a JWT to manage session ID’s under the nbaidentity cookie. If we take this string out, decrypt it as URL and then Base64 we get the following.
{
"sub": "VALUE",
"iss": "VALUE",
"exp": DATE,
"nonce": "VALUE",
"nbaCustomer": "ACCOUNT GUID",
"region": "EU",
"iat": 1
}
To test specifically for IDORs in the application I made two accounts: Bill Door and Will Door


Now with two accounts in possession (with which I can test for IDORs ethically and within the Rules of Engagement), and more importantly two GUIDs and two JWTs, I can proceed to slam my head on every endpoint that I could Fuzz for.
And…. Nothing
The NBA is an extremely popular program running on HackerOne. IDORs are typically low hanging fruit which can be picked up by automatic scanners like Autorize for Burpsuite. So perhaps I was too late.
Then I found an endpoint in the very last place I looked. /api/badges/
/api/badges/ is an extremely inconspicuous endpoint, its entire functionality is based entirely around pseudo-achievements awarded by gambling and voting on the site, which you can just look at and maybe show your friends from a screenshot.
/api/badges/ did not care about any of the other fields in the JWT, whilst other API endpoints rejected a web request if the “nonce” did not match other checks in the session token. EDIT: Looking back I think it’s obvious they planned for future expansion of these features like being able to share them with friends.
So if we create a GET request from the account of Bill substituting the "nbaCustomer" GUID with the GUID of Will, we receive the content of Will’s badge page.
Exploitation
“Big Deal!” you say. “It’s not a security flaw,” the man from HackerOne says.
At the very least, I think it demonstrates a flaw in the access controls of the API (that’s the A in the CIA triad). But three problematic points come to mind when I see the API response.
"member_since": A key part of the NBA account recovery system is asking when an account was created. This API endpoint can be used to see the exact date an account was created. A potential attacker could leverage this in a targeted social engineering attack, possibly recovering the account.


"Proud **** Fan": NBA fans have a high likelihood of their password being their favourite player or team. An AI Generated word list could be then used to brute-force the account password. For an account with a high amount of badges, this would be more of the case as a die hard fan would be more likely to have more badges and therefore more likely to have a NBA based password.
"Game Watcher" : The “Game Watcher” badge could reveal to would-be-hackers if the user is paying for NBA League Pass and act as reconnaissance to see if a target is fiscally worth investing time into hacking.
Mitigation
Simply apply the same protection which comes with every other endpoint to that of badges, if future plans include the use of badges in a social context then the best bet is to add authentication to only allow sharing between whitelisted accounts.
Conclusion
Now this isn’t a groundbreaking exploit by any means, but It’s my first step into the world of bug bounty. Hopefully, this is a lesson in ingenuity in how to turn a seemingly innocuous endpoint (‘/api/badges/‘) into an attack surface for social engineering, bruteforcing or target reconnaissance.
Something that I haven’t touched on yet is the bulletproof reliability of GUIDs and them being almost impossible to bruteforce. I was kind of banking on there being another endpoint which leaks GUIDs.
The attack surface for the NBA is huge, there are dozens of interlinked APIs which my nose is telling me has to go wrong somewhere. For now, I’m hanging up my sneakers on this program because I don’t actually care about basketball. It was a nice soiree into Bugbounty but I’m going to move onto more relevant targets.
Update
Timeline:
- Aug 12: Bug Submitted to NBA
- Aug 16: Bug Acknowledged by NBA
- Sep 11: Bug fixed via server-side validation of the
`nbaCustomer`ID. - Sep 25: Low Bounty Awarded for Improper Access Control

