Authentication and Authorization Attacks

Concepts

Authentication vs. Authorization

Authentication is verifying who the user is - confirming the user is who they claim to be. Authorization (Access Control) is verifying what the user is allowed to do.

Analogy: At the airport you show your passport to check-in staff - that’s authentication. At the gate you show your boarding pass - that’s authorization. Two separate checks, two separate controls.


Authentication Attacks

Brute Force (Single Parameter)

When a login form has no lockout or IP rate limiting, you can automate credential guessing with ffuf.

Steps:

  1. Enable Burp Suite intercept and submit any login request - observe the parameters and headers.
  2. Save the request: right-click → Copy to file → e.g. auth0x01.req
  3. Identify the parameter to fuzz (e.g. username=jeremy&password=jeremy).
  4. Replace the target parameter value with FUZZ:
    username=jeremy&password=FUZZ
    
  5. Run ffuf:
    ffuf -request auth0x01.req -request-proto http -w /usr/share/wordlists/seclists/Passwords/Common-Credentials/xato-net-10-million-passwords-10000.txt:FUZZ -ac -c -v
  6. Examine the result - look for a response with a different size or status code:
    [Status: 200, Size: 1808, Words: 494, Lines: 47]
      * FUZZ: letmein
    

Tip: -ac (auto-calibrate) filters out baseline responses automatically. If your wordlist is very small (<~100 entries), ffuf may not have enough data to calibrate - check size/status manually instead.


Cluster Bomb Brute Force (Unknown Username + Password)

Use this when you don’t know either credential. It tests every combination of username × password.

Important: If the application locks accounts after N failed attempts, keep your password list to N-1 entries (e.g. top 4 passwords) and iterate across many usernames instead of locking one account.

Steps:

  1. Enable Burp Suite intercept and submit a login request.
  2. Save the request to auth0x03.req.
  3. Replace both parameters with distinct keywords:
    username=FUZZUSER&password=FUZZPASS
    
  4. Create a short password list if needed:
    printf '123456\npassword\npassword123\nletmein\n' > pass.txt
  5. Run ffuf in cluster bomb mode:
    ffuf -request auth0x03.req -request-proto http -w /usr/share/wordlists/seclists/Usernames/top-usernames-shortlist.txt:FUZZUSER -w pass.txt:FUZZPASS -mode clusterbomb -c -v
  6. With a small wordlist, skip -ac and compare response sizes manually - a successful login will have a noticeably different size.

Attacking MFA

MFA adds a second verification step. Common weaknesses to test:

QuestionAttack
Is the code short / numeric only?Brute force the token
Does the code expire?Reuse a captured token
Can one token be used for multiple users?Submit token with a different username
Is the username submitted again at the MFA step?Intercept and swap it

Intercept & Username Swap Attack:

  1. Log in with your own account (e.g. jessamy:pasta) and reach the MFA step.
  2. Obtain your valid MFA token.
  3. Before submitting, turn on Burp intercept.
  4. In the intercepted request, change the username field to the victim’s username (e.g. jeremy).
  5. Forward the request - if the application validates the token independently of the username, you log in as the victim.

The root cause: the server trusts the username value in the MFA POST body rather than binding the MFA session to the authenticated identity from step 1.


Authorization Attacks

Vertical vs. Horizontal vs. Context-Dependent Access Control

TypeDefinitionExample
VerticalRestricts functions by roleRegular user can’t access admin panel
HorizontalRestricts resources by ownerUser A can’t read User B’s profile
Context-dependentRestricts based on application stateCan’t check out with an empty cart

When any of these controls is missing or bypassable → Broken Access Control.


IDOR - Insecure Direct Object Reference

Occurs when an application exposes an internal identifier (ID, number, filename) in a request and fails to verify the requester is authorized to access that object.

Example URL: http://target.com/account?id=1009

Best practice on bug bounties: Always use two accounts you control (User A and User B). Access User B’s data using User A’s session. This limits your blast radius to your own test accounts.

Brute-forcing IDs with ffuf:

Generate a number range:

seq 1000 9999 > 1000-9999.num

Find all accessible accounts:

ffuf -u 'http://localhost/labs/e0x02.php?account=FUZZ' -w 1000-9999.num -c -v

Find accounts with a specific attribute (e.g. admin):

ffuf -u 'http://localhost/labs/e0x02.php?account=FUZZ' -w 1000-9999.num -c -v -mr "Type: admin"

When you find admin usernames via IDOR, treat them as targets for credential attacks - you now have a valid username list.

API note: In API-driven apps, IDOR is called BOLA (Broken Object Level Authorization) - same concept, different name.


Broken Access Control - Manual Test

Setup:

  • Always create / use two accounts: User A and User B
  • Capture both sessions/tokens

What to look for in requests:

  • Any parameter identifying a user: username, user_id, email, account_number, account
  • If present in the URL, body, or headers → it’s a candidate for testing

The Test:

  1. Perform an action as User A (view profile, update bio, access a resource)
  2. Intercept the request in Burp Suite
  3. Keep User A’s session token but change the user identifier to User B’s
  4. Send the request - if it succeeds → Broken Access Control

JWT Tokens

JSON Web Tokens are commonly used for API authentication.

Structure: header.payload.signature (each part is Base64-encoded, separated by dots)

eyJhbGciOiJIUzI1NiJ9   ← header
.eyJ1c2VyIjoiamVyZW15In0  ← payload (claims: user, role, etc.)
.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c  ← signature
  • Decode manually: echo "PAYLOAD_PART" | base64 -d
  • Or paste the full token into https://jwt.io

Where to find them in requests:

  • Authorization: Bearer <token> header
  • Cookies (e.g. session=<token>)
  • Query string or request body

Key things to test:

  • Is the signature verified? (If missing → tamper with claims)
  • Can you change role: staff to role: admin?
  • Full JWT attack coverage → see API Hacking course or jwt.io docs

API Endpoints - Reference

Login:

curl -X POST -H "Content-Type: application/json" -d '{"username": "admin", "password": "password123"}' http://localhost/labs/api/login.php

Get account info:

curl -X GET "http://localhost/labs/api/account.php?token=<JWT>"

Update account (PUT):

curl -X PUT -H "Content-Type: application/json" -d '{"token": "<JWT>", "username": "jeremy", "bio": "New bio."}' http://localhost/labs/api/account.php

BFLA (Broken Function Level Authorization): Using User A’s token to call a write endpoint targeting User B. Same idea as IDOR - just at the function/action level rather than the object level.


Autorize - Burp Suite Plugin

Autorize automates horizontal privilege testing across many endpoints. Instead of manually duplicating every request, it automatically replays each request using a second user’s token and flags whether authorization was bypassed or enforced.

Setup:

  1. Install Jython standalone JAR from jython.org
  2. In Burp Suite: Extensions → Extension Settings → set Jython JAR path
  3. BApp Store → install Autorize
  4. In the Autorize tab, paste User B’s session token/cookie into the token field → click OK → turn Autorize on

How to use:

  1. Browse the app as User A (normal actions: view profile, update bio, access restricted areas)
  2. Autorize automatically replays each request using User B’s token
  3. Review the results:
    • Bypassed → User B can perform User A’s action → Broken Access Control finding
    • Enforced → properly blocked
    • Is enforced?? → status codes matched but response body differed → investigate manually

Autorize is especially valuable for large apps with 20+ endpoints where manual testing becomes error-prone.


Checklists

Authentication Testing Checklist

Login Form

  • Is there a rate limit or lockout on failed attempts?
  • Is the lockout per-IP, per-account, or both? (per-IP only → rotate IPs to bypass)
  • Does the error message reveal whether the username or password was wrong? (username enumeration)
  • Is there a username enumeration vector via response timing?
  • Is there a “remember me” option? Where is the token stored, and how long does it last?
  • Does the login endpoint accept JSON as well as form data? (potential WAF bypass)

Brute Force

  • No lockout → brute force password for a known username
  • Lockout present → cluster bomb with many usernames + top 3-4 passwords
  • CAPTCHA present → test if it can be reused, removed, or bypassed

MFA

  • How many digits is the OTP? (≤6 numeric → brute force candidate)
  • Does the OTP expire? What is the window?
  • Can the same OTP be used more than once?
  • Is the username re-submitted at the MFA step? → swap it to another user
  • Is there a fallback method (SMS, email, backup code)? Test each independently
  • Can you skip the MFA step entirely by going directly to a post-login URL?
  • Does the MFA session cookie work for a different account?

Password Reset

  • Is the reset token guessable or short?
  • Does the reset token expire?
  • Can a reset token be used more than once?
  • Is the token leaked in a Referer header when clicking a link in the reset email?
  • Can you reset another user’s password by manipulating a parameter (e.g. email=victim@x.com)?

Registration

  • Can you register with an existing username/email (account takeover via duplicate)?
  • Is email verification enforced, or can you use a fake address?

Authorization / Access Control Checklist

Setup (always do this first)

  • Create two accounts at the same privilege level: User A and User B
  • If roles exist, also create/access an Admin account
  • Capture all sessions/tokens before starting

Horizontal Privilege Escalation (IDOR / BOLA)

  • Identify every parameter that references a resource by ID (id=, account=, user_id=, file=, etc.)
  • Substitute User B’s identifier while authenticated as User A
  • Test in URL query string, request body, and headers/cookies
  • Test all HTTP methods: GET (read), POST (create), PUT/PATCH (update), DELETE
  • Test indirect references too - e.g. filename=report.pdf → try filename=../other_user/report.pdf
  • For APIs: brute-force ID ranges to enumerate objects (ffuf + -mr)

Vertical Privilege Escalation

  • As a standard user, directly request admin-only URLs (e.g. /admin, /dashboard/admin)
  • As a standard user, call admin-only API endpoints
  • Remove or downgrade the role claim in a JWT and check if signature is verified at all
  • Check if adding ?admin=true or &role=admin to a request changes behaviour

Function-Level Authorization (BFLA)

  • With User A’s token, call every write/delete endpoint targeting User B’s data
  • Use Autorize plugin to automate replay of all requests with User B’s token
  • Check if lower-privilege roles can access higher-privilege functions even if the UI hides them

State & Context

  • Can you access a later step in a multi-step flow directly (e.g. skip payment, go to confirmation)?
  • Can you replay a single-use action (e.g. re-submit a completed order)?
  • Does the app enforce ownership checks on file downloads/exports?

JWT & Session Management Checklist

Token Discovery

  • Where is the token stored? (Authorization header, cookie, localStorage, query string)
  • Is it a JWT? Paste into https://jwt.io to inspect claims and algorithm

JWT-Specific Attacks

  • Is the signature present? If not → freely tamper with claims
  • Algorithm none attack: strip the signature and set "alg": "none" in the header
  • RS256 → HS256 confusion: if the server accepts both, sign with the public key as the HMAC secret
  • Weak secret: try cracking with hashcat -a 0 -m 16500 <token> wordlist.txt
  • Can you change "role": "user" to "role": "admin" in the payload?
  • Does the kid (key ID) header allow path traversal or SQL injection?

Session Tokens (non-JWT)

  • Is the token random enough? Capture 10+ tokens and check for patterns
  • Does the token change after login? (session fixation risk if not)
  • Does the token change after privilege escalation (e.g. after MFA completes)?
  • Is the token invalidated server-side on logout?
  • Does the token expire? What is the idle and absolute timeout?
  • Is the session cookie scoped with HttpOnly, Secure, and SameSite?

Token Transmission

  • Is the token ever sent in a URL query string? (exposed in logs, Referer headers)
  • Is the token sent over HTTP anywhere?

API Access Control Checklist

  • Create (or compromise) two accounts - User A and User B
  • Capture both sessions/tokens
  • With User A’s token, call every read endpoint targeting User B’s identifier
  • With User A’s token, call every write endpoint targeting User B’s identifier
  • Check if role claims in JWT can be tampered with
  • Test vertical access: can a standard user reach admin-only endpoints?
  • Test undocumented endpoints - try common paths (/api/v1/admin, /api/users, /api/debug)
  • Test all HTTP methods on each endpoint - server may accept DELETE even if docs don’t mention it
  • Check if API versioning exposes older, less-secured endpoints (/api/v1/ vs /api/v2/)
  • If successful → Broken Access Control (IDOR / BOLA / BFLA depending on context)