From OTP Flaw to Full Access: A 3-Day Recon Breakdown


This post is a walkthrough of how I stumbled upon a severely exposed setup during a casual recon session.
The website name is intentionally left out. I’ve tried to redact anything sensitive or identifiable.
This is purely for educational purposes, no harm intended.
Day 1: Initial Discovery
I randomly ended up on this website and tried logging in.
I found that even though my proxy was on, it still let me go through OTP verification. That felt odd.
Out of curiosity, I searched otp
in the code and found this logic:
if (enteredOtp === sessionStorage.getItem('otp'))
They were storing the OTP in sessionStorage
. I also found a hardcoded api_key
value that allowed me to make any request using their API. This meant you could log in with any number and use their API.
The implementation had development stage leftovers like commented-out code and client-side logic for important flows, suggesting the site was either in active development or transitioning.
I chose this as my recon target.
I first tried some basic IDORs, didn’t get anywhere. Turned out the site was using session cookies that were freshly generated every time a browser session was opened. Solid implementation made any IDOR attempt ineffective. Then I moved to subdomain and directory enumeration and found multiple OMS-related environments and staging links. That gave me a bigger surface to work with.
Day 2: Open Git == Open Secrets
I started testing all OMS-related subdomains and did basic /FUZZ
wordlists.
One of them had exposed .git
directories:
.git/HEAD
.git/config
etc.
I used GitTools to dump the entire Git repository, including all historical commits.
From there, I went through the source and found:
Hardcoded API keys for Swiggy, Bitly, Paytm etc.
Internal logic and routing
MySQL credentials
Random phone numbers and emails commented out
Real locations and debug info left inside the code
I ran some of the numbers through a Truecaller bot, one belonged to the CEO, and another seemed like a staff member.
I did try logging into the DB, but thankfully remote access was restricted.
Day 3: Revisited FUZZ — Jackpot
I reran /FUZZ
on all subdomains, this time using a different wordlist, and surprisingly found a /config
endpoint on another OMS site.
This one exposed their live database contents:
User records: id, name, number, email
Delivery locations
Product listings
Chat logs with customers
My own test account entry (confirmed real-time updates)
At this point, the amount of data I had access to was too much for something publicly reachable.
Reporting Attempt
Yes.
I reached out to the individuals associated with the exposed contact information and shared a screenshot showing a page containing a name, number, and the affected URL, purely to highlight the issue.
While I didn’t receive a response or acknowledgment, I later noticed that one of the vulnerable URLs had been quietly fixed. Since some action was taken, I decided not to follow up further.
What I Didn’t Explore (But Could’ve)
Even after all this, I felt like I barely scratched the surface.
I didn’t dig deep into the production websites I had discovered or the Android app (which I noticed later).
Honestly, I already had access to so much sensitive information, and with no responsible response from their side, I didn’t feel it was worth digging deeper.
Final Thoughts
This kind of setup is a textbook example of:
Poor security hygiene
Lack of separation between dev and prod environments
Exposing sensitive files to the public
Leaving secrets and PII scattered throughout a codebase
If you’re a developer or part of an engineering team:
Don’t expose
.git
or/config
endpointsDon’t hardcode secrets in production
Don’t implement OTP on the client side
And please… clean up your code before pushing it live
Subscribe to my newsletter
Read articles from Anshul Negi directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
