Skip to content
All modules
CoreModule 13 of 27120 minutes

Sessions, tokens and access control

Read and forge JWTs and Flask sessions, break the assumptions behind a session cookie, and win the races that a request boundary creates.

Assumes3. Hashes, identification and cracking12. Client-side: XSS and the browser's trust model

By the end you can

  • Decode a JWT and identify the attack its header enables
  • Forge an alg=none token and recover a weak HMAC secret offline
  • Unpack and re-sign a Flask session once the secret key is known, and find that key first
  • Choose between horizontal and vertical access-control tests, and prove each with two accounts
  • Exploit a check-then-act window with concurrent requests, and explain why a retry loop is not the same thing
  • Recognise a request-smuggling primitive from a header pair a proxy and a server read differently

1. Read

2. Use the tools

In the order they come up while solving. Read what each one does, or go straight to the workspace tab that runs it.

3. Try one now

Generated in your browser and checked in your browser. No account, nothing to download, and a fresh one whenever you want another.

4. Practise on the real thing

Real picoCTF challenges that use these techniques, easiest first. 19 match in total - see the full index.

Common mistakes

The wrong turns this topic reliably produces. Written as the mistake rather than the rule, because the rule is easy to agree with and easy to walk straight past.

  • Editing the payload of a signed token and expecting it to be accepted. The attack has to defeat the signature - alg confusion, a known secret, or a kid that points somewhere useful - not ignore it.
  • Decoding a Flask session and calling it forged. It is signed too; without the secret key you have read access and nothing more.
  • Testing a race with a for loop. Sequential requests never overlap; the window needs concurrency, and often needs the requests to arrive in the same packet.
  • Cracking an HMAC secret against re-encoded JSON. The signature covers the base64url header and payload exactly as transmitted, so pretty-printing or reordering the claims before testing candidates makes the correct secret look wrong.
  • Fixing an expired token by editing exp and nothing else. Expiry is checked after the signature, so a token that fails verification never reaches the claim you changed and the error tells you nothing about it.

Checkpoint

Take a JWT-protected endpoint and reach an admin-only response, stating which of the three token weaknesses you used and why the other two did not apply.

Teaching note

Students conflate 'I can read the token' with 'I can change the token'. Decode a JWT in front of them, edit the role claim, watch the server reject it, and only then introduce the three ways the signature actually fails. The rejection is the lesson.

Go deeper

The lessons above are written to get you through a challenge. These go after the subject instead. Each one opens our notes on that chapter - what it argues, what to take from it and where it stops - so this is somewhere to read now rather than a book to buy first. Nothing here is affiliate-linked or sold by us.

Every book the curriculum cites has a page in the library.