Global CMS Chaos: How I Scored a $15,000 Bounty Across Two Programs
Introduction: The Hunt Begins
Picture this: I’m sipping instant coffee at 2 a.m., staring at my screen, ready to dive into another bug bounty hunt on a private HackerOne program. My mission? Unearth vulnerabilities that could make even the most seasoned sysadmin sweat. Little did I know, this adventure would lead me to uncover a chain of flaws that exposed sensitive data, hijacked accounts, and impacted two programs — private and public. Buckle up, because this story is a wild ride through API chaos, WAF battles, and a $15,000 payout that felt like winning the cybersecurity lottery.
The Journey: A Curious Error Sparks a Discovery
It all started with a seemingly innocent endpoint that threw an error: “GET_USER_INFO: Error code (17) — User id is missing.” Sounds like the server was politely telling me, “Hey, buddy, you’re doing it wrong.”
But in bug bounty land, errors are like treasure maps — they often lead to gold. Intrigued, I fired up Burp Suite to inspect the request. No User-Id parameter in sight. Nada. Zilch. So, I decided to get creative and tossed in a User-Id: null header. The server blinked and responded with a slightly different error: “User Id format is incorrect.”
Jackpot! The server was clearly paying attention to my rogue header. Time to escalate things. I sent the request to Burp Intruder, set the User-Id header to cycle through numeric values (1 to 1000), and waited for the magic. The results? A lots of PII — emails, phone numbers, full names, addresses, and more — spilled out for valid User-Id values. I identified Hundreds valid PII instances in that range alone. With a sequential User-Id pattern, a broader sweep (say, 1 to 100,000) could’ve exposed thousands. Yikes.
But then, the Akamai WAF (aka the cybersecurity bouncer) crashed my party with a 403 Forbidden error, yelling, “Too many requests, pal!”
No worries — I slipped past it using Burp Suite’s IP Rotate extension, like sneaking into a club with a fake mustache. Success! The PII floodgates were open again.
Raising the Stakes: From PII to Mass Lockouts
With a treasure trove of emails in hand, I tested the login page. Using a harvested email (let’s call it user@victim.com) and a wrong password, I triggered a warning: “Login failed, password is incorrect, account will be locked after one more attempt.” Two failed attempts later, I confirmed the system’s lockout mechanism. This was big. An attacker could use these emails to lock out accounts en masse by spamming incorrect passwords. Imagine locking out store managers across the company’s branches in the Philippines, Thailand, and Hong Kong during Black Friday — pure chaos! It’s like telling a retail chain, “Sorry, your managers are on a forced coffee break.”
The impact was already screaming High severity: widespread PII exposure, potential for mass account lockouts, and violations of data protection laws like GDPR and PDPA. Fines? Lawsuits? Reputational damage? Check, check, and check. But I wasn’t done yet. I submitted my initial findings to the program, rated as High with a CVSS score of 8.2, but the triager downgraded it from High to Medium severity, citing that account lockouts weren’t permanent. Ouch. My hacker pride took a hit, but it lit a fire to dig deeper.
The Plot Twist: Tokens and a Surprise Collaborator
While reviewing the leaked responses, I noticed something I’d missed — a juicy accessToken and refreshToken buried in the data. How did I overlook that? Blame it on 2 a.m. coffee brain. I reached out to my bug bounty buddy, @rac_fckscty (the best source code sleuth I know), to see if he was invited to the same program. After sharing redacted details, he confirmed the tokens could enable session hijacking or unauthorized access to privileged accounts, like store managers or admins.
I studied the tokens and realized I could manipulate the server’s response. Using a harvested User-Id response with valid tokens, I attempted a login with random credentials. The server predictably grumbled, “Invalid credentials.” But when I swapped the response body with the leaked one containing the accessToken and refreshToken, the server redirected me to an OTP form. Wait, what?
I was one step away from the dashboard without valid credentials. Now, the challenge was bypassing the OTP.
The OTP Takedown: A Dash of Creativity
The OTP form was guarded by a response parameter: “needOTP”: true. Simple enough, right? I thought, “What if I just… flip the switch?” I modified the response to “needOTP”: false and hit send. Poof! No OTP form. Instead, I landed on the private program’s CMS dashboard with full control. It was like walking into a bank vault because someone left the door unlocked. I could manage content, tweak product prices, add items, or even delete them — across all global branches, including Asia, the US, and the UK. Oh, and this CMS also powered the public program’s domain. That’s right — my private program bug had just crashed into the public program’s assets. Double trouble!
Note: Apologies, folks — I can’t share screenshots of the dashboard or sensitive details since this is a private program. Gotta keep things ethical and respect the program’s confidentiality. Trust me, the chaos was real, but you’ll have to take my word for it! 😎
The Impact: From Private to Public Chaos
This wasn’t just a private program vulnerability anymore. The CMS connected to both programs, meaning an attacker could wreak havoc on a global scale. Change product prices on the mobile app? Done. Add fake products to the website? Easy. Delete critical data? Why not? The potential for disruption was massive, affecting confidentiality, integrity, and availability.
I updated my report, emphasizing the critical severity and the cross-program impact, but the triager couldn’t reproduce my proof-of-concept (PoC). Sigh. Time to bring out the big guns — a video PoC.
A day after submitting the video, the report was triaged, and three days later, the program awarded me $5,000 — their max payout for the private program. But I knew this bug’s impact spanned the public program, which had a higher bounty range ($7,500–$10,000). I appealed, politely pointing out the cross-program chaos. The program asked for a PoC showing the public program impact, so I went all-in: I added fake products, tweaked website data, and even threw in a stored XSS for good measure (imagine a pop-up saying, “Hacked by meepmerp!”). I also uncovered IDOR and SQL injection flaws in the app, but that’s a story for another day.
The triager’s response? “Hi @meepmerp, thank you for the PoC, we’ll reconsider the tier for this report, please remove everything you left.” Oops, my bad! I cleaned up my PoCs like a good hacker and waited. A few days later — BAM! — an additional $10,000 bounty landed, bringing the total to $15,000 in the bag! Cue victory dance.
Lessons Learned: Persistence Pays Off
This hunt taught me a few things:
- Errors are gold. A simple error message can unlock a treasure trove of vulnerabilities.
- WAFs are speed bumps, not walls. IP rotation saved the day.
- Never settle. If I hadn’t appealed the initial bounty, I wouldn’t have hit that $15,000 mark.
Most importantly, always test responsibly. I stopped short of exploiting further without permission, ensuring I stayed within ethical bounds. As for the program, they’re now patching those endpoints, tightening authentication, and probably sweating a little less.
The Hunt Never Ends
This journey was a rollercoaster of late-night coding, WAF battles, and triumphant PoCs. To my fellow hunters, keep digging, stay curious, and don’t be afraid to appeal when you know your bug’s worth it. And always remember: Your secure code today might be vulnerable tomorrow.
Thanks for joining my bounty-hunting journey! Loved it? Leave some claps to keep the vibes high. ✨ Got a question? Feel free to comment or shoot me a PM! Bye for now.