Skip to content

Lesson pack 12 · Core · 90 minutes

Client-side: XSS and the browser's trust model

Get your JavaScript to run in someone else's page, past a CSP and an admin bot - and see why polluting a prototype changes every object in the process.

Print this page for a paper plan - the navigation and links drop out.Student-facing version

Before the session

  • Nothing to install. Students need a browser and https://ctfpal.com. Confirm the room can reach it once; after that it works offline.
  • Read the lesson yourself first - about 11 minutes.
  • Have one worked example ready to paste. The classroom link builder on the instructor page turns it into a URL that opens preloaded.

Objectives

Written as things a student can do afterwards, so they can be assessed rather than asserted.

  1. Distinguish reflected, stored and DOM-based XSS by where the sink is, not where the payload went in
  2. Read a Content-Security-Policy and name what it forbids, what it permits, and the gadget that gets past it
  3. Exfiltrate a cookie or a bot's session to a collector you control
  4. Recognise a prototype pollution sink and chain it to a gadget already in the page
  5. Explain the same-origin policy in terms of what it protects, and name three legitimate exceptions to it

Running order (90 min)

TimeWhat happens
0:00-0:09Frame the problemWhat the category looks like when you meet it cold, and why the naive approach fails.
0:09-0:27Teach the methodThe technique itself, on the board or from the lesson. No tools open yet.
0:27-0:50Demonstrate liveSame technique, in the workspace, on your worked example. Narrate every choice.
0:50-1:21Practice setStudents work the challenges. Circulate rather than present.
1:21-1:30Checkpoint and wrapCollect the artefact, name what comes next.

Tools used

  • HTML entity decoder - Decode named, decimal, and hexadecimal HTML entities back to text - including the mixed-form entities used to slip past XSS filters.https://ctfpal.com/?tool=html-entity-decoder
  • URL decoder and encoder - Percent-decode and encode URL components, including double-encoded payloads and `+`-as-space form encoding.https://ctfpal.com/?tool=url-decoder
  • Web attack payload catalog - Curated payloads for SQL injection, XSS, SSTI, SSRF, GraphQL, and deserialization, organised by what you are trying to establish.https://ctfpal.com/?tool=payload-catalog
  • HTTP security header analyzer - Analyse CSP, HSTS, X-Frame-Options, and CORS headers on a response - and find the gaps in a Content-Security-Policy that make XSS exploitable.https://ctfpal.com/?tool=security-header-analyzer
  • Regex tester with match offsets and capture groups - Test regular expressions live against sample text, with every match’s offset, capture groups, and named groups broken out.https://ctfpal.com/?tool=regex-tester

Reading

Practice set

Real picoCTF challenges tagged with this module’s techniques, easiest first. Assign the first three in class and the rest as homework.

  1. Bookmarklet - picoCTF 2024, easy
  2. dont-use-client-side - picoCTF 2019, easy
  3. Includes - picoCTF 2022, easy
  4. Insp3ct0r - picoCTF 2019, easy
  5. Inspect HTML - picoCTF 2022, easy
  6. Local Authority - picoCTF 2022, easy
  7. Client-side-again - picoCTF 2019, medium
  8. findme - picoCTF 2023, medium
  9. login - picoMini by redpwn, medium
  10. Java Script Kiddie - picoCTF 2019, hard
  11. Java Script Kiddie 2 - picoCTF 2019, hard
  12. noted - picoCTF 2022, hard

Checkpoint (gradeable)

Land a payload that makes the challenge's bot issue a request to a URL you control, carrying its session, and state which CSP directive you had to work around.

Deliberately a produced artefact rather than a quiz question: it is either there or it is not, which makes it fast to mark and hard to bluff. Every tool in ctfpal is deterministic, so two students who did the work correctly hand in the same value.

Where the room gets stuck

The admin bot confuses people more than the payload does. Draw the flow once - your payload is stored, a headless browser with the flag cookie visits, your JavaScript runs as that browser - and most of the class stops trying to exfiltrate their own cookie.

  • Testing with alert(1) against an admin bot that has no alert handler. The proof of execution has to be something you can observe, which usually means a request to a collector.
  • Reading encoded output as safe. Encoding is context-sensitive: HTML-escaping inside a script block or a URL attribute protects nothing.
  • Chasing the injection point in DOM XSS. The bug is in the sink - innerHTML, document.write, a template compiler - and the source may be untouched.
  • Reusing one payload across contexts. An attribute, a template literal, a JSON blob and an existing script block each need a different break-out, and the payload that fires in one of them is inert in the other three.
  • Reading a CSP as a wall rather than as an allowlist. A permitted CDN carrying a JSONP endpoint or an old framework build is a script source under your control, so the directive worth studying is what it admits, not what it blocks.

If a student wants the subject, not the answer

Chapter-level references, so a student can be pointed at twenty pages rather than at a book. Nothing here is required to complete the module.

  • Bug Bounty Bootcamp, Vickie Li. Chapter 6, Cross-Site Scripting. Sorts XSS by sink and context, which is the taxonomy that actually predicts which payload works.
  • Bug Bounty Bootcamp, Vickie Li. Chapter 19, Same-Origin Policy Vulnerabilities. The rule the whole module depends on, plus the exceptions attackers live in.
  • Real-World Bug Hunting, Peter Yaworski. Chapter 7, Cross-Site Scripting. Disclosed reports where the interesting part is where the payload landed, not what it was.
  • Hunting Security Bugs, Tom Gallagher, Bryan Jeffries, and Lawrence Landauer. Chapter 10, HTML Scripting Attacks. Predates most modern defences, which makes the underlying parsing problem unusually visible.

If you finish early

  • Hand out a challenge from the cross-CTF index in this category - each one has published solutions to compare afterwards.
  • Run the same input through Identify and let the class argue with the ranking. Disagreeing with a confidence score is where the technique actually lands.
  • Ask a student to break their own example - construct an input that defeats the tool, and explain why.

Take this into a room

Markdown files, built here in your browser. They print, they open in anything, and they carry the challenge text - so the session works with no network in the room.