Authentication Bypass
Source: PortSwigger Web Security Academy Author: Johan Beysen
1. What Is Authentication Bypass?
Authentication vulnerabilities let an attacker bypass or undermine an application's login mechanisms — by taking over another account or gaining access without valid credentials.
Difference from access control:
| Authentication | Authorization | |
|---|---|---|
| Question | Are you who you say you are? | Are you allowed to do this? |
| Failure | Someone logs in as someone else | Someone does more than they're allowed to |
| Result | Account takeover | Privilege escalation |
Causes:
- Weak brute-force protection
- Logic flaws in the authentication flow
- Predictable tokens or cookies
- A flawed MFA implementation
- Poor password reset mechanisms
2. Detection
| Test | What you're looking for |
|---|---|
| Different error messages | "Invalid username" vs "Invalid password" |
| Response time | A longer response for a valid username |
| Rate limiting | Lockout after X attempts? IP-based? |
| The "remember me" cookie | A predictable or decodable value? |
| The password reset flow | A predictable token? Uses the Host header? |
| The MFA step | Skippable by going straight to the next endpoint? |
| Default credentials | Admin/admin, admin/password, ... |
| Status code manipulation | Forcing 302 → 200 in the response |
Burp Suite
- Intruder for brute force and username enumeration
- Sequencer for token entropy analysis
- Match & Replace for response manipulation
3. Username Enumeration
The application reveals whether a username is valid through subtle differences.
3.1 Error Messages
Invalid username ← username doesn't exist
Invalid password ← username does exist
Invalid username or password ← correct: no info
Even small spelling or formatting differences count:
Invalid username or password. ← period present
Invalid username or password ← period absent → different code path
3.2 Response Time
If the application only hashes the password for an existing username, a valid username takes longer:
Username: nonexistent → response: 85ms
Username: administrator → response: 300ms ← hashing takes time
Test in Burp Intruder → compare the "Response received" and "Response completed" columns.
3.3 HTTP Status Code
Username doesn't exist → HTTP 200 (login page again)
Username exists → HTTP 302 (redirect after a wrong password)
3.4 Enumeration via Other Channels
Registration form: "This email address is already in use"
Password reset: "We'll send an email if this account exists" ← some apps state this directly
4. Brute Force Attacks
4.1 Simple Brute Force
Burp Intruder → Sniper → payload: a password list
4.2 Credential Stuffing
Testing leaked username:password combinations on the target site:
# Via ffuf
ffuf -u https://target.com/login \
-X POST \
-d "username=HFUZZ&password=WFUZZ" \
-w usernames.txt:HFUZZ \
-w passwords.txt:WFUZZ \
-fc 200
4.3 Bypassing Rate Limiting
Account lockout
Brute force sometimes triggers account lockout — even on real accounts. Coordinate this with the client before you start.
5. Logic Flaws in the Authentication Flow
5.1 Skipping a Step
The application assumes the user has completed step 1 before reaching step 2:
Step 1: POST /login → check credentials
Step 2: GET /2fa → enter MFA code
Step 3: GET /account → logged in
Attack: step 1 with the attacker's valid credentials, then
skip step 2 by requesting /account?uid=admin directly
5.2 The User in a Hidden Field or Cookie
If username is client-controllable:
5.3 Status Code Manipulation
If a 302 redirect to /login signals that authentication failed, but the response body already contains the dashboard content:
Response: 302 Found → Location: /login
→ In Burp Match & Replace: replace "HTTP/2 302" with "HTTP/2 200"
→ The browser shows the dashboard
5.4 A Predictable "Stay Logged In" Cookie
Cookie: stay-logged-in=d2llbmVyOjUxZGMzMGRkYzQ3M…
→ Base64 decode: wiener:51dc30ddc473d43a6011e9ebba6cd601
→ MD5 hash of the password → the hash for "peter" matches!
→ Generate for admin: Base64(administrator:MD5("password"))
6. Password Reset Vulnerabilities
6.1 A Predictable Reset Token
Token 1: reset-2024011501
Token 2: reset-2024011502
Token 3: reset-2024011503 ← a pattern is visible
If tokens are incremental, timestamp-based or guessable → an attacker requests a reset for the admin, guesses the token.
6.2 Host Header Poisoning
The application builds the reset link using the Host header:
POST /forgot-password
Host: attacker.com ← modified
→ The victim receives an email with the link:
https://attacker.com/reset?token=abc123
→ The victim clicks → the attacker receives the token in server logs
Test by replacing the Host header with a Burp Collaborator URL.
6.3 Token Reuse & No Expiration
1. Request a reset token for your own account
2. Use the token, but save it
3. Does the token stay valid after use? → Reuse it on another account
4. Does the token not expire? → Use it again weeks later
6.4 Reset via Predictable User Data
?token= (empty token)
?token=0 (null/zero)
A reset based on the username in the request body → change it to admin
7. MFA Bypass
7.1 Skipping a Step
After a successful first step (username/password), the server sometimes already sets a session cookie:
1. Log in with valid credentials
2. The /2fa page is shown
3. Navigate directly to /account or /dashboard
4. The session is already active → access granted
7.2 Brute-Forcing the MFA Code
If there's no rate limiting on the MFA endpoint:
For 6-digit codes: 000000–999999 (max 1,000,000 attempts).
7.3 Response Manipulation
MFA verification via a status code or boolean in the response:
{"verified": false} ← server response
→ Match & Replace: "false" → "true"
→ Or: 302 to /login → 302 to /account
7.4 Backup Codes
- Applications sometimes provide backup codes during MFA setup
- Backup codes live on the account settings page
- Via IDOR: read another account's backup codes
8. Default Credentials
Always try these first on admin panels, login pages and management interfaces:
| System | Username | Password |
|---|---|---|
| General | admin |
admin / password / 123456 |
| General | administrator |
administrator / admin |
| Router/IoT | admin |
admin / (empty) |
| Tomcat | tomcat |
tomcat / s3cret |
| Jenkins | admin |
admin |
| Grafana | admin |
admin |
| MySQL | root |
(empty) / root |
| phpMyAdmin | root |
(empty) |
| Kibana | elastic |
changeme |
# Automated testing
hydra -L users.txt -P passwords.txt https://target.com http-post-form \
"/login:username=^USER^&password=^PASS^:Invalid credentials"
9. Cheat Sheet
Username Enumeration Signals
| Signal | Present? |
|---|---|
| A different error message for a valid username | |
| A longer response time for a valid username | |
| A different status code | |
| A redirect for a valid username, no redirect for invalid | |
| The registration form confirms an existing account |
Brute Force Checklist
□ Is rate limiting present?
□ Lockout after X attempts?
□ Lockout per IP or per account?
□ Is X-Forwarded-For trusted for rate limiting?
□ Does a successful login reset the counter?
□ Is there a CAPTCHA? Bypassable?
Password Reset Checklist
□ Token in the URL? (leaked via Referer)
□ Is the token predictable or incremental?
□ Does the token not expire?
□ Is the token reusable after use?
□ Is the Host header used in the reset URL?
□ Is the username in the request body client-controllable?
MFA Bypass Checklist
□ Can the step be skipped straight to /account?
□ Is brute force on the MFA code possible?
□ Response manipulation (false → true)?
□ Is the account session already active before MFA is completed?
□ Are backup codes retrievable via IDOR?
Interesting Endpoints
/login /signin /auth
/forgot /reset-password /password-reset
/2fa /mfa /verify
/account /dashboard /admin
/api/login /api/auth /api/token