CriticalIDOR → Account Takeover· 5 min read

One Vendor Number, the Whole Directory — Then the Keys

The app identified vendors by a number in the request. Read anyone's profile with it; then change their email and own the account.

Target anonymized · a global retailer's vendor portal

Some findings are one bug. This was one broken idea — "trust the vendor number in the request" — expressed in two endpoints, and together they went from information disclosure to full account takeover.

The spark

Every request the portal made carried a "vendor number" identifying whose data to load. Mine looked sequential. Whenever an app hands the client the identifier that decides whose record to serve, I stop and pull the thread.

Digging in

Read first. I changed the vendor number on a profile-fetch request to a neighbouring value and got back a different company's full business profile: legal name, contact person, email, phone, category. No ownership check, and — crucially — no rate limiting. So this wasn't just "read one stranger"; it was "enumerate the entire vendor directory."

Then the obvious escalation: if reads aren't authorised, are writes?

Write next. The profile-update request carried the same number. I set it to a victim's value and changed the email address on their account. The server accepted it.

Once you can set a victim's account email, you don't need their password — you ask the site to reset it for you.

The exploit

The chain, with two test accounts I controlled:

  1. Update-profile request, vendor number set to the victim, email set to mine → 200 OK.
  2. Trigger the standard password reset → the reset link lands in my inbox.
  3. Reset, log in. The account is mine. The victim did nothing.

Impact

Two impacts stacked: mass harvesting of every vendor's business PII by enumeration, and a zero-interaction account takeover of any vendor. Either one is serious; together they're critical.

The fix

Derive the vendor context from the authenticated session, never from a number in the request. Authorize reads and writes against that principal, and rate-limit the lookup so enumeration isn't free.

idoraccount-takeoverenumerationbroken-access-control

All identifiers, targets and payloads in this post are anonymized or defanged. Findings were reported and resolved through responsible disclosure.