What is cross-site scripting and how does it work?
What is cross-site scripting and how does it work?: Give a clear, practical overview of cross‑site scripting (XSS): what it is, how it works, the three types (Reflected, Stored, DOM‑based), and a concise manual testing workflow with copy‑paste payloads, troubleshooting, and defenses. • Knowledge • Cross-site scripting • xss, cross-site-scripting
🎯 Objective
Give a clear, practical overview of cross‑site scripting (XSS): what it is, how it works, the three types (Reflected, Stored, DOM‑based), and a concise manual testing workflow with copy‑paste payloads, troubleshooting, and defenses.
🧩 What I’m covering
- What is XSS? A client‑side vuln that lets an attacker run JS in a victim’s browser, bypassing same‑origin isolation for that app.
- How it works: The app returns attacker‑supplied JavaScript (or HTML that leads to execution). The victim’s browser executes it within their session.
- Impact: Act as the user (read/modify data, actions), and if the victim is privileged, potentially full app takeover.
🧭 Types of XSS (with quick examples)
1) Reflected XSS
The payload is sent in the request and reflected in the immediate response without safe handling.
Example flow
https://insecure-website.com/search?term=gift
→ Response contains: You searched for: giftAttack (context‑appropriate payload)
https://insecure-website.com/search?term=%3Cscript%3Ealert(document.domain)%3C/script%3EIf the context is inside an attribute or text, adapt the payload accordingly (see payloads below).
2) Stored (Persistent) XSS
The payload is stored server‑side (DB, file, cache) and later served to other users.
Submit
POST /post/comment HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
postId=3&comment=%3Cscript%3Ealert(1)%3C%2Fscript%3E&name=Carlos&email=c%40ex.netEffect Any user viewing the post gets the stored script in the response and it executes.
3) DOM‑based XSS
Client‑side JS reads attacker‑controlled source (e.g., location, document.URL) and writes to an unsafe sink (innerHTML, eval, attribute setters).
Vulnerable snippet
var search = document.getElementById('search').value;
var results = document.getElementById('results');
results.innerHTML = 'You searched for: ' + search;If an attacker controls #search, they can inject something like:
<img src=x onerror=alert(1)>Common sources
location, document.URL, document.referrer, window.name, localStorage, sessionStorage, history.*
Common sinks
innerHTML/outerHTML, document.write, eval, setTimeout(string), location, someEl.src/href, JSON.parse (on attacker input)
🔍 Manual testing workflow (reflected & stored)
- Test every entry point. Query params, body params, path segments, and (cautiously) headers.
- Seed a unique marker (random 8–10 char alphanum). Confirm where it’s reflected.
- Identify context. Text, attribute (quoted/unquoted), JS string, URL, etc.
- Try a context‑fit payload. Start minimal; iterate if it gets filtered or encoded.
- If it looks good in Repeater, move to a browser and prove execution with
alert(document.domain)oralert(1). - For stored XSS, find entry→exit links (e.g., comment → blog view). Verify persistence across requests/users.
🧪 Testing DOM‑based XSS
- Use DevTools: inject a marker in the source (
?q=R4nd0mX) and search the DOM (Elements panel) for it. - Identify the sink and adapt the payload: e.g., if innerHTML, use an event‑handler element (
<img onerror=...>). - For execution sinks (
eval, timers), use the Sources panel to set breakpoints on references to the source value and watch it flow to a sink. - If using Burp’s browser, try DOM Invader to automate source→sink discovery.
📎 Copy‑paste payloads (by context)
Text/HTML insertion (sanitizer often strips <script> → use events)
<img src=x onerror=alert(1)>
<svg onload=alert(1)></svg>With cookie read (if not HttpOnly):
<img src=x onerror=alert(document.domain)>Attribute‑quoted breakout
Single‑quoted:
'"><img src=x onerror=alert(1)>Double‑quoted:
"\><svg onload=alert(1)></svg>JavaScript string
');alert(1);//URL / navigation sinks
javascript:alert(1)Encoded:
javascript%3Aalert(1)Quick encoded snippets for URLs
%3Cimg%20src%3Dx%20onerror%3Dalert(1)%3E
%27%22%3E%3Csvg%20onload%3Dalert(1)%3E%3C%2Fsvg%3E🧰 Tips & Troubleshooting
- Nothing executes? You may be in the wrong context; switch payload style (text vs. attribute vs. JS string).
- HTML appears encoded (
</>)? That point likely escapes output; search for a different reflection or another sink. javascript:blocked or CSP present? Prefer DOM insertion payloads (<img onerror=...>,<svg onload=...>).document.cookieempty? Session cookie might be HttpOnly; usealert(1)or exfiltrate other accessible DOM data instead.- Stored flows can be overwritten; test promptly after submitting your marker.
🔒 Defense (dev notes)
- Use context‑aware escaping for HTML, attributes, URLs, and JS strings.
- Avoid unsafe sinks (
innerHTML,eval, string‑built handlers). PrefertextContent, safe DOM APIs. - Validate and allowlist URLs before navigation; reject
javascript:/data:. - Enforce a strong CSP (nonces/hashes; no
unsafe-inline; blockdata:/javascript:as needed). - Mark auth cookies HttpOnly; Secure; SameSite (defense‑in‑depth; doesn’t fix XSS).
✅ Key takeaways
- XSS = attacker JS running in your origin. Know your sources and sinks.
- Reflected, Stored, DOM cover server and client‑side paths to execution.
- Always identify the context and use a matching payload.
- Harden apps with safer APIs, escaping, and CSP; treat cookie flags as additional layers, not cures.