June 9, 2026
BBP#3: The Boat Speaker— From Shopping Cart to Account Takeover
How a lazy Sunday shopping session turned into finding two critical vulnerabilities in a checkout SDK used by 400+ merchants
Devender Rao
4 min read
It was 2021. I was at home, sitting on my bed, trying to buy a new pair of Boat speakers. Just me, my BrupSuite, open in Kali Linux running in the background like always.
At this point, proxying my traffic through Burp was , like a habit . Like how some people open YouTube while eating — I just had Burp running. Always.
When I moved to "Add to Cart" Section it asks the Phone number and as A Active Bug Hunter Your first thought will be you will be looking everything to find bugs and try to bypass , at that time i was on full active mode and which make curious and I check the burp history
The Checkout That Didn't Stay Quiet
Boat was using GoKwik as their checkout gateway — a fairly popular solution for Indian e-commerce at the time. The flow was simple: enter your phone number, get an OTP, verify, and you're in.
But Burp saw something Developer do not want :)
As I typed in my phone number and hit submit — before I'd even touched the OTP field — a response came back. A 200_ _OK And inside it was something that had absolutely no chance it should had there at that moment:
{
"statusCode": 200,
"statusMessage": "User Validated",
"data": {
"phone": "9012345678",
"otp_required": true,
"auth_token": "eyJhbGci0iJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJj...",
"default email": "aaaaaa@gmail.com"
}
}{
"statusCode": 200,
"statusMessage": "User Validated",
"data": {
"phone": "9012345678",
"otp_required": true,
"auth_token": "eyJhbGci0iJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJj...",
"default email": "aaaaaa@gmail.com"
}
}My eyes went straight to auth_token.
Then back to otp_required: true.
Then back to default_email. WHY ??
Wait. They're returning the JWT before the OTP is verified? The flag literally says OTP is required — and they're sending the token in the response anyway with the User Email address Cool
Bug #1 — The Token That Didn't Wait for the OTP
Here's the thing about authentication flows: the whole point of an OTP is to verify that the person entering the phone number actually owns it. The auth token should only arrive after that verification.
The auth_token itself contains the email address,
The auth_token in that response was a fully valid JWT. And with that token, I could directly hit their address API:
GET /v1/address/:phone
Authorization: Bearer eyJhbGci0i...GET /v1/address/:phone
Authorization: Bearer eyJhbGci0i...Response? The complete saved address of that user. Name, full address, pincode — everything a logged-in user would see in their profile.
No OTP. No verification. Just a phone number and a token that wasn't supposed to be mine yet.
The scariest part? I didn't have to do anything clever. I just… read the response. The token was sitting right there in plain text, handed to anyone whose traffic happened to be visible — whether that's a man-in-the-middle, a compromised network, or a bored security researcher buying speakers on a Sunday.
Bug #2 — The OTP That Could Be Guessed by a Script
While I was digging around, I noticed something else.
The OTP endpoint had no rate limiting.
GoKwik was using a 4-digit OTP. That's 10,000 possible combinations. And the server would happily accept guess after guess after guess, with no lockout, no CAPTCHA, no throttle.
Do the math: at even a modest request rate, you can brute-force a 4-digit OTP in minutes. Which means:
- Enter any victim's phone number
- Start a script
- Get the OTP
- Walk straight into their account
No phishing. No social engineering. Just arithmetic.
Any platform running GoKwik's Node SDK at the time — Boat included — was exposed to this. An attacker could take over any user's checkout account, grab their saved addresses, and potentially place orders in their name.
The Root Cause
After reporting both issues, GoKwik's team traced the problem back to their Node SDK. The token was being returned too early in the authentication lifecycle — a bug in the SDK's response serialisation, not the API design itself. That's the sneaky thing about shared SDKs: one bad line of code silently propagates across every merchant who imports the package.
To their credit, GoKwik's team was responsive. They acknowledged both findings, identified the Node SDK as the root cause, and pushed a fix.
Wait — How Big Was This, Actually?
Boat had 800,000+ registered users and GoKwik was powering checkouts for 250+ brands in 2021 — meaning that many users' saved addresses, phone numbers, and account access were potentially up for grabs with just a phone number and a brute-force script.
The Response I Got
A few days after reporting, I received a message from their team. Something along the lines of:
"Our team has reviewed your submission and they found these issues are legitimate. As we are already working on our bug bounty program and it's still not ready. We'll let you know once our program is complete."
Classic. The "we'll let you know" that never comes. I've stopped holding my breath for that notification.
But here's where it gets interesting — GoKwik, being genuinely appreciative, offered me something as a gesture: a Backend Engineer role at their company.
And look, I respect that. Truly. It was a kind offer.
But bhai… I'm a security guy. You want me to sit and write Node.js endpoints when I could be finding the next JWT leak in someone else's checkout flow? Agar maine backend join kar li, toh Burp Suite aur Kali Linux mujhe kabhi maaf nahi karenge. They'd haunt me. Every git push would feel like a betrayal.
My terminal is dark-themed for a reason. It's not for writing CRUD APIs — it's for watching HTTP responses that have no business returning auth tokens before the OTP fires.
Some people are built for building. I'm built for breaking things (ethically, of course 😅).
What I Learned (Again)
The most interesting bugs aren't hidden. They're just not being looked at.
Nobody was trying to exploit GoKwik that day. But Burp was open, the response was right there, and I happened to notice that auth_token was showing up somewhere it had no right to be.
You don't always need a sophisticated attack chain. Sometimes you just need to read the response carefully.
Also: always proxy your shopping traffic. You never know what's in the cart.
Both vulnerabilities were responsibly disclosed directly to GoKwik in 2021. The team confirmed the root cause in their Node SDK and issued a patch. No user data was accessed or stored during this research.
Follow me for more stories from the bug-hunting bucket.
Thanks For reading :)
Follow for More:-
Twitter:- root_rao