@
目录
- 一、XSS之盲打
- 🎯 漏洞原理
- 二、XSS 之过滤
- (一)攻击者视角:常见的过滤绕过技巧
- 1. 标签与事件绕过
- 2. 关键字绕过
- 3. DOM 型过滤绕过
- (二)防御者视角:如何构建可靠的防御体系
- 1. 输入验证(白名单优先)
- 2. 输出编码(最核心的防线)
- 3. 使用安全的库(避免重复造轮子)
- 4. 内容安全策略
- (一)攻击者视角:常见的过滤绕过技巧
前言:本文仅用于合法授权的渗透测试场景,旨在帮助开发者识别XSS漏洞、提升Web应用安全性,严禁用于未授权攻击!网络安全无小事,违规操作将承担相应法律责任。
一、XSS之盲打
XSS盲打(Blind XSS)是存储型XSS的一种特殊变体,其核心挑战在于攻击者无法直接看到攻击结果。这通常发生在用户输入被存储在服务器(如数据库、日志文件)中,但不会在当前页面立即显示,而是由其他用户(如管理员)在后台或其他页面查看时才会触发。
🎯 漏洞原理
- 注入点与触发点分离:攻击者提交恶意脚本后,只能看到类似“提交成功”或“感谢反馈”的通用提示,无法确认脚本是否真的被存储或何时被执行。
- 延迟性与隐蔽性:恶意脚本被持久化存储后,需要等待特定用户(如管理员登录后台查看留言、日志)访问包含该脚本的页面时,攻击才会真正触发。
- 攻击目标:由于普通用户可能不会访问所有包含XSS点的页面,盲打的主要目标通常是权限较高的管理员,以实现会话劫持或权限提升。

在留言这里输入 ,并提交,当管理员再次登录的时候,就会触发 playload。

当然,实战中,可以通过该漏洞获取到管理源的 cookie、session等信息。
二、XSS 之过滤
XSS 过滤是防御跨站脚本攻击的核心手段,但也是攻防对抗最激烈的领域。很多开发者以为“把 <script> 标签删掉就安全了”,但攻击者总有各种办法绕过这些简单的检查。
这里结合 pikachu 靶场梳理了常见的绕过技巧和真正的防御方案。

(一)攻击者视角:常见的过滤绕过技巧
在渗透测试或 CTF 中,如果你发现输入被过滤了,可以尝试以下思路:
1. 标签与事件绕过
很多过滤器只拦截 <script>,却忽略了其他标签。
- 利用其他标签:
<img src=x onerror=alert(1)>(利用图片加载失败事件)<svg onload=alert(1)>(利用 SVG 矢量图标签)<iframe src=javascript:alert(1)>(利用内联框架)<body onload=alert(1)>(利用页面加载事件)
- 利用伪协议:
<a href="javascript:alert(1)">点击</a><img src="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' onload='alert(1)'/>">(利用 Data URI)
2. 关键字绕过
如果 onerror、alert 被过滤,可以尝试:
- 大小写混淆:
<ImG sRc=x oNeRrOr=alert(1)> - 双写/多写过滤:
<img srconerror=alert(1)>(如果过滤器只删除一次,剩下onerror) - 利用注释:
<scr<!-- -->ipt>alert(1)</script>或<img src=x onerror=alert/*x*/(1)> - 编码绕过:
- 十六进制:
<img src=x onerror=alert(1)> - 十进制:
<img src=x onerror=alert(1)> javascript:伪协议的编码:<a href="javascript:alert(1)">
- 十六进制:
3. DOM 型过滤绕过
针对你之前遇到的 DOM XSS,如果前端 JavaScript 过滤了 # 后面的内容,可以尝试:
- 利用
?代替#:如果代码只处理 hash,可以尝试在查询参数中注入。 - 利用
location.search:如果过滤了location.hash,但使用了location.search,攻击方式同上。
(二)防御者视角:如何构建可靠的防御体系
作为开发者,永远不要依赖“黑名单”(即只过滤已知的危险词)。因为攻击向量无穷无尽,你永远无法列全。正确的做法是白名单策略和上下文相关的输出编码。
1. 输入验证(白名单优先)
不要试图清理所有恶意代码,而是只允许合法的输入通过。
- 严格校验格式:例如用户名只允许字母、数字和下划线,长度限制在 3-16 位。
- 正则示例:
/^[a-zA-Z0-9_]{3,16}$/
- 正则示例:
- 拒绝非法输入:对于不符合白名单格式的数据,直接拒绝处理(返回 400 错误),不要尝试“清理”它。
2. 输出编码(最核心的防线)
这是防御 XSS 最有效、最通用的方法。根据数据插入的位置(上下文)进行不同的编码。
| 输出场景 | 编码规则 | 示例 |
|---|---|---|
| HTML 文本内容 | 将特殊字符转为 HTML 实体 | < 转为 <,> 转为 > |
| HTML 属性值内 | 除了实体编码,还要编码引号 | " 转为 ",' 转为 ' |
| JavaScript 代码内 | 使用 Unicode 或十六进制编码 | </script> 转为 \x3c\x2fscript\x3e |
| URL 参数内 | 使用百分号编码 (Percent-encoding) | < 转为 %3C," 转为 %22 |
3. 使用安全的库(避免重复造轮子)
手动编写过滤逻辑极易出错,应使用经过社区广泛验证的库。
- 前端 (JavaScript/Node.js):
- DOMPurify:专门用于净化 HTML,允许你定义白名单标签(如
<b>,<i>,<a>),同时移除所有危险的事件属性(如onerror)和脚本。
- DOMPurify:专门用于净化 HTML,允许你定义白名单标签(如
- 后端:
- Java:使用 OWASP Java HTML Sanitizer 或 Jsoup。它们基于白名单策略,可以安全地处理富文本。
- Python:使用 Bleach(基于白名单的 HTML 清理器)。
- PHP:使用
htmlspecialchars()函数进行转义。
4. 内容安全策略
这是浏览器的“最后一道防线”。即使你的代码有漏洞,CSP 也能阻止恶意脚本的执行。
- 核心思想:告诉浏览器,页面只能加载指定来源的脚本。
- 配置示例:
Content-Security-Policy: default-src 'self';- 这表示只允许加载同源(和当前网站同一个域名)的脚本,内联脚本(
<script>...</script>)和eval()默认会被禁止。
- 配合 Nonce:对于必须执行的内联脚本,可以使用
nonce机制,为脚本生成一个随机令牌,只有带上正确令牌的脚本才能执行。
