Login
ChallengesLearn
Scoreboard
Teams
SPNZ

LearnCross Site ScriptingXSS Review & Practice
Cross Site Scripting·Lesson 12 of 12

XSS Review & Practice

A curated set of progressively harder XSS challenges against fresh endpoints. Reflected, stored, DOM, blind — no hand-holding. The XSS course final.

Intermediate22 min
XSSReviewPractice
Loading lesson…
PreviousXSS Case Studies

© 2026 SPNZ.

Terms of ServicePrivacy PolicyCookie Policy

This is the XSS course final. Five challenges that combine reflected, stored, DOM, and blind XSS techniques. No hints beyond what is in the challenge description — you will need to identify the injection context, choose the right payload, and prove that the payload executes.

What you'll be able to do
  • Craft a reflected XSS payload that executes in an HTML context.
  • Bypass attribute-context escaping with event-handler payloads.
  • Exploit a DOM source (hash fragment) that reaches a dangerous sink.
  • Identify a stored XSS payload that survives across requests.
  • Deliver a blind XSS payload that triggers in an admin panel.
Key terms
Blind XSS
An XSS payload that executes not in the attacker's own session but in a different user's — typically an admin or moderator viewing a stored value in a backend panel. The attacker must use an out-of-band channel to receive the callback.
Polyglot payload
A single input string that is syntactically valid in multiple contexts — for example, a string that works both as an HTML attribute value and as a JavaScript string — allowing it to bypass context-specific escaping.
Content sniffing bypass
A technique where the browser interprets a response as a different MIME type than intended, often exploited to bypass CSP when the server serves user content with a generic Content-Type.
What is it?

Bringing it all together

The five challenges below test every XSS technique covered in this course. Each challenge presents a vulnerable endpoint, a code snippet showing where the injection lives, and a pass/fail test. Your payload must pass the test — for example, executing alert(document.domain) or triggering a simulated callback to a blind XSS listener.

The challenges progress from a simple reflected XSS (challenge one) to a blind XSS against a simulated admin panel (challenge five). You will need to think about context: is the injection in an HTML element body, an attribute value, a JavaScript string, or a URL? The correct payload depends on the answer.

Challenge difficulty curve
Mini Map
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.
Try it

Challenge range

Work through each challenge in order. Type your payload into the input and press Submit. The simulator tests whether the payload achieves the required effect — for example, popping an alert in the simulated browser or sending a callback to the listener endpoint.

stagingxss-range.io/challenges
xss-range
Solved
0 / 5
12345
Challenges
ContextReflected XSS — HTML context

The search endpoint echoes your query directly into a <p> element. No escaping, no filter.

Vulnerable code
router.get("/search", (req, res) => {
  res.send(`<p>You searched for: ${req.query.q}</p>`);
});
Objective

Make the browser execute alert(document.domain) on the search results page.

Your payload
Test: alert(document.domain) must fire
Real-world relevance

Bug bounty programmes use this exact format

Every major bug bounty platform — HackerOne, Bugcrowd, Intigriti — uses the same format as these challenges. The programme provides a target endpoint, the researcher identifies the injection context, and submits a proof-of-concept payload. The best reports include the vulnerable code snippet, the working payload, and a screenshot of the alert box or exfiltration attempt.

Blind XSS in particular is a staple of high-severity bug bounty findings. Many applications have stored XSS that only executes in an admin panel — the researcher must deliver the payload through a customer-support ticket, a user-report form, or a profile field that an administrator later views. The callback URL confirms execution.

Mitigation

How to defend against the full spectrum

Defending against all five challenge types requires the same layered approach: context-aware escaping at every output point, a strict CSP that disables inline scripts, and automated scanning that catches DOM sinks before they reach production. Blind XSS is the hardest to defend against because the vulnerable code may only execute in an internal panel that the security team does not routinely scan.

javascriptsafe
// VULNERABLE — reflected HTML context
router.get('/search', (req, res) => {
  res.send('<p>You searched for: ' + req.query.q + '</p>');
});

// SAFE — escape at the output layer
router.get('/search', (req, res) => {
  const q = escapeHtml(req.query.q ?? '');
  res.send('<p>You searched for: ' + q + '</p>');
});

// VULNERABLE — DOM hash → innerHTML
const tab = location.hash.slice(1);
document.getElementById('tab-content')!.innerHTML = tabs[tab];

// SAFE — allowlist the sink value
const tab = location.hash.slice(1);
const allowed = ['profile', 'settings', 'billing'];
const content = allowed.includes(tab) ? tabs[tab] : tabs['default'];
document.getElementById('tab-content')!.textContent = content;

// Blind XSS defence — strict CSP + input validation
// If the admin panel renders user content, use sandboxed iframes
// or a separate origin that cannot access admin cookies.
Further reading
  • HackerOne — XSS severity reference(HackerOne)
  • Intigriti XSS challenge archive(Intigriti)
  • Blind XSS — OWASP Cheat Sheet(OWASP)
Key takeaways

What to remember

  • Challenge one: HTML context — a simple script tag or img onerror payload proves reflection.
  • Challenge two: Attribute context — break out of the attribute with a quote, then inject an event handler.
  • Challenge three: DOM hash — the fragment is client-side only; server never sees it. Use textContent not innerHTML.
  • Challenge four: Stored XSS with CSP — find a CSP bypass vector (JSONP, CDN script, or dangling markup).
  • Challenge five: Blind XSS — the payload fires in an admin panel. Use an out-of-band callback to prove execution.

Knowledge check

0/3 answered · 0 correct
  1. 1.What is the correct payload for an HTML-context reflected XSS where the input is echoed inside <p>INPUT</p>?

  2. 2.What distinguishes blind XSS from reflected XSS?

  3. 3.In the DOM hash challenge, why does the server-side scanning tool fail to detect the vulnerability?