Cookies
Cookies are key-value pairs stored by the browser on the client side. When a server sends a Set-Cookie header in an HTTP response, the browser saves it locally and includes it in subsequent requests to the same domain. Browsers enforce limits on cookie size and quantity per domain to prevent abuse and excessive disk usage.
Sessions
Sessions store user state on the server. Upon login, the server creates a unique session ID and typically sends it to the client via a cookie. The client returns this ID with each request so the server can identify the user. However, sessions face challenges in load-balanced environments unless session data is shared across servers (e.g., via Redis or a database).
Tokens and JWT
Tokens offer a stateless alternative to sessions. JSON Web Tokens (JWTs) encode user claims in a compact, URL-safe format. A JWT consists of three Base64Url-encoded parts separated by dots:
- Header – Specifies the token type and signing algorithm.
- Payload – Contains claims (e.g., user ID, roles, expiration time).
- Signature – Validates token integrity using a secret or private key.
Example header:
{
"alg": "HS256",
"typ": "JWT"
}
Example payload:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"exp": 1516242622
}
The signature is computed as:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
Common JWT Exploitation Techniques
-
Algorithm Confusion (
alg: none) Some implementations skip signature verification if the header specifies"alg": "none". A attacker can remove the signature and setadmin: truein the payload. -
Weak Secret Brute-Forcing If HMAC is used with a weak secret, tools like
hashcatcan recover it:hashcat -m 16500 jwt.txt -a 3 -w 3 wordlist.txt --forceOnce the secret is known, the attacker can forge valid tokens.
-
Token Expiration Bypass Modify the
exp(expiration time) claim to a future timestamp after decoding and re-signing the token with the cracked secret.
WebGoat Lab Walkthrough
Start WebGoat:
sudo java -jar webgoat-server.jar --server.port=8888 --server.address=<KALI_IP>
Access at http://<KALI_IP>:8888/WebGoat.
Challenge 4: alg: none Attack
- Capture the JWT from a request.
- Decode it using a tool like jwt.io.
- Change the header to:
{"alg":"none","typ":"JWT"} - Set
admin: truein the payload. - Remove the signature part (leave only two segments).
- Send the modified token—authentication succeeds if the server doesn’t validate signatures for
none.
Challenge 5: Brute-Force Secret
- Save the target JWT to
jwt.txt. - Run
hashcatwith a wordlist to recover the HMAC secret. - Use the cracked secret to re-sign a token with an extended
expvalue. - Submit the forged token to bypass expiration.
Challenge 7: Replay with Modified Claims
- Extract the JWT used during checkout.
- Decode it and change the algorithm to
none. - Update the
expto a future Unix timestamp. - Reconstruct the token without a signature and send it in the request.
- The server accepts it if signature validation is skipped for
none.
These exercises demonstrate critical misconfigurations in JWT handling, emphasizing the need for strict validation, strong secrets, and secure algorithm choices.