Scanner group

Authentication and sessions

These scanners all test how a server decides who you are and how many tries you get. Four of them send requests as a client that should be refused: with no session, with a forged token, or with a made-up identity. The fifth reads the page the crawler already captured. Each one turns a difference the server should not show into a finding: a reply that varies with the account, a credential that works without a valid signature, a counter that never trips.

5 scanners5 DAST3 need --depth deepup to Critical

How this group works

Three clients, three doors. Each step below is one scanner of the group sending its characteristic request, or in the last step reading what it already has. Watch which client sends it, what comes back, and which part of the reply is the finding.

Anonymous client no session, no token Forged token real payload, fake signature Snapshot reader sends nothing at all /api/login credentials in, token out /api/forgot-password mails a reset link /api/me needs a valid login Request → reply → decision the shared question The scanner plays a client that should not get in: no session, a forged token, a made-up identity. It reads what the server gives away: status, body, timing or a count of accepted requests. One scanner reads no reply at all. See step 6. JWT scanner · forged token GET /api/me Bearer eyJ… (alg: none) 200 {"id":"u_42","role":"admin"} FLAG: a token with no signature was accepted also weak secrets, RS to HS key confusion and missing exp, iat or iss claims Auth bypass scanner · two logins, no session no such user → 401 User not found admin@test.com → 401 Invalid password FLAG: the reply tells the accounts apart also lockout, default credentials, reset token leaks and Authorization header bypass Password reset scanner · 5 requests, one email POST /api/forgot-password admin@test.com 202 202 202 202 202 FLAG: five resets, no 429 also email enumeration and a token of 20+ characters in the reply body Rate limit scanner · sequential run POST /api/login ×150, 0.05 s apart 150 accepted, no 429 FLAG: HIGH, no rate limiting a 429 at request 21 is only INFO; also bursts of 10, 50, 100 and a new-identity check Session scanner · reads the captured page Set-Cookie: sid=… no HttpOnly, no Secure app.js: localStorage.setItem("token", …) FLAG: any script on the page can read the token also a session JWT that outlives 24 hours when the scanner is given one Shared rule: the finding is a difference the server should not show: a reply that varies with the account, a forgery that works, a counter that never trips.

1Three clients and three doors. Each scanner picks the client that should be refused and sends the request a legitimate user would send. The decision rests on what the reply reveals, or on how many requests it takes before the server pushes back.

2JWT. The scanner takes the real token from the login session, rebuilds it with alg: none, a weak secret or a swapped algorithm, and sends it to a protected endpoint. A 2xx that a garbage-token control did not also get means the server never checked the signature.

3Auth bypass. Two logins that differ only in the email. Different error phrases, a timing gap above 0.5 s or different status codes reveal which accounts exist. It deliberately carries no session: with one, its anonymous probes would not be anonymous.

4Password reset. Five reset requests in a row. If none is answered 429, an attacker can flood an inbox or grind through tokens. The same endpoint is also compared across two emails and searched for a token in the reply.

5Rate limit. The endpoint's own request repeated up to 150 times. Reaching the end without a 429 is HIGH. A 429 gives a measured threshold, and further bursts and an identity switch probe how the limit is keyed.

6Session. No request goes out. The scanner reads the HTML, scripts and cookies the crawler captured, and flags tokens in localStorage and auth cookies without HttpOnly or Secure.

Scanners in this group

At a glance

ScannerWhat it looks atWhat it reportsSeverityNeeds
JWT scannerThe session JWT, a protected endpoint, scripts for tokens in URLsForged tokens accepted (alg none, weak secret, key confusion); missing exp, iat, iss; a token in a URLInfo to CriticalURL; an authenticated session (forgery tests are skipped without a token)
Session scannerThe captured snapshot: JavaScript, response cookies, optionally the session JWTA token in localStorage; auth cookies missing HttpOnly or Secure; a JWT valid more than 24 hoursMedium to HighURL only; runs at quick depth; sends no request
Auth bypass scannerLogin, reset and auth-required endpoints, matched by URL substringUsername enumeration, no lockout, default credentials, reset token in a reply, Authorization header bypassMedium to CriticalURL; --depth deep; deliberately not auth-aware
Password reset scannerEndpoints whose URL looks like forgot or reset passwordEmail enumeration, five unthrottled resets, a token in the reply bodyMedium to CriticalURL; --depth deep; auth-aware when a session exists
Rate limit scannerEndpoints with login, signup, password, reset, token or otp in the URLNo 429 in 150 requests; the measured threshold; mixed bursts; a limit that resets on a new identityInfo to HighURL; --depth deep; auth-aware except the identity test
Depth and the session

The session scanner runs in the default quick scan. The rate limit, auth bypass and password reset scanners are the three aggressive probes added by --depth deep. On an authenticated deep scan the crawl's session is handed to every HTTP scanner that exposes _auth_headers: rate limit and password reset take it, while auth bypass is skipped on purpose because its tests depend on the absence or forging of authentication.

Why this class matters

Why it matters

Authentication is the front door and the session is the key it hands out. A token in localStorage or a cookie without HttpOnly turns any XSS into account takeover. A JWT that is accepted without a valid signature lets anyone mint tokens for any user. Without lockout or rate limiting, guessing is free, and a reset flow that confirms which emails exist or returns its own token makes takeover a single request. Nothing here needs a clever payload: the server simply answers what it should have refused.

Real-world breaches

British Airways (2018). Injected JavaScript could reach client-side storage, enabling exfiltration of payment data and session tokens. iCloud (2014). No lockout or rate limit on the Find My iPhone API allowed brute-force attacks on celebrity accounts. Dunkin' Donuts (2015). Credential stuffing against an app with no rate limiting took over accounts and drained stored value. Snapchat (2014). The password reset flow allowed enumeration and confirmation of phone numbers linked to accounts. jsonwebtoken CVE-2015-9235. The library accepted alg: "none" by default, a complete authentication bypass for apps that did not restrict algorithms.