目录
在 Web 安全领域,XSS(Cross - Site Scripting)漏洞是一个备受关注的话题。虽然在一些人眼中,XSS 漏洞的危害程度和可利用价值似乎不大,但实际上,在高手手中,一个不起眼的 XSS 漏洞也可能引发严重的安全问题。
一、XSS 漏洞分类
(一)传统分类
XSS 常年位居 Web top10 漏洞之列。一般传统的分类包括反射型 XSS(Reflected Cross - Site Scripting)、持久型 XSS(Persistent Cross - Site Scripting,包括存储、DOM 等类别)。根据跨站的成因或者特征进行分类,还有 Flash 跨站(Flash - based Cross - Site Scripting)、mXSS 跨站(Mutation - based Cross - Site Scripting)、UBB 跨站(UBB - based Cross - Site Scripting)、宽字节跨站(Wide - Byte based Cross - Site Scripting)等等,这些分类存在很多重叠部分。
(二)国外分类
国外比较精确地将跨站分类为:服务端跨站(Server XSS)、客户端跨站(Client XSS),然后再细分反射型或者存储型等,这种分类是根据漏洞形成点的位置来看的。
(三)部分分类详细介绍
- mXSS 跨站(Mutation - based Cross - Site Scripting):
- 主要是在 DOM 操作过程中浏览器渲染造成的畸变引起的。例如,当对 DOM 节点的内容进行多次赋值操作时,可能会发生字符编码转换或解析不一致的情况,从而导致脚本内容被意外执行。以下是一个更详细的示例:
var element = document.createElement('div');
element.innerHTML = '<span data-attr="<script>alert(1)</script>">Test</span>';
// 这里将一段包含脚本的字符串作为HTML实体编码后放入innerHTML
var newElement = document.createElement('div');
newElement.innerHTML = element.getAttribute('data-attr');
// 再次获取并赋值给新元素的innerHTML,可能会触发mXSS漏洞,弹出警告框
- UBB 跨站(UBB - based Cross - Site Scripting):
- 在论坛里使用较多,如果存在 XSS,可以类似这样利用:
[img ]javascript :alert();[/ img]
,在转成 html 代码的时候造成跨站。以下是一个可能在论坛中出现的简单示例,假设论坛使用了一个简单的 UBB 解析函数parseUBB
:
- 在论坛里使用较多,如果存在 XSS,可以类似这样利用:
function parseUBB(text) {
// 简单的替换规则,实际可能更复杂
return text.replace('[img ]', '<img src="').replace('[/ img]', '">');
}
var userInput = '[img ]javascript :alert();[/ img]';
var output = parseUBB(userInput);
// 此时output可能被直接插入到页面中,导致XSS
- Flash 跨站(Flash - based Cross - Site Scripting):
- Flash 跨站通常是利用 Flash 文件中的安全漏洞来实现跨站脚本攻击。例如,一些恶意攻击者可能会修改 Flash 文件的内部代码,使其在播放过程中能够执行恶意的 JavaScript 脚本。以下是一个简化的示例,假设存在一个有漏洞的 Flash 对象,其有一个名为
exploitFunction
的方法可以被外部调用:
- Flash 跨站通常是利用 Flash 文件中的安全漏洞来实现跨站脚本攻击。例如,一些恶意攻击者可能会修改 Flash 文件的内部代码,使其在播放过程中能够执行恶意的 JavaScript 脚本。以下是一个简化的示例,假设存在一个有漏洞的 Flash 对象,其有一个名为
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/sharing/flash/swfobject.swf" width="550" height="400">
<param name="movie" value="vulnerableFlash.swf"/>
<param name="allowScriptAccess" value="always"/>
<param name="quality" value="high"/>
<embed src="vulnerableFlash.swf" allowScriptAccess="always" quality="high" width="550" height="400" type="application/x-shockwave-flash"></embed>
</object>
<script>
// 攻击者可以在页面中调用Flash对象的exploitFunction方法来执行恶意脚本
var flashObj = document.getElementsByTagName('object')[0];
flashObj.exploitFunction('alert("XSS via Flash");');
</script>
- **宽字节跨站(Wide - Byte based Cross - Site Scripting)**:
- 宽字节跨站主要是利用数据库的字符编码设置不当以及一些编程语言对字符处理的特性来实现的。例如,在某些数据库(如MySQL)中,如果字符编码设置为GBK等宽字节编码,攻击者可以通过构造特殊的字符组合来绕过输入验证机制。以下是一个简单示例,假设一个网站有一个搜索功能,其后台使用GBK编码处理用户输入,并直接将用户输入嵌入到SQL查询中:
```php
<?php
$searchTerm = $_GET['search'];
// 假设这里没有对用户输入进行足够的验证
$conn = mysqli_connect("localhost", "username", "password", "database");
$sql = "SELECT * FROM products WHERE name LIKE '%$searchTerm%'";
$result = mysqli_query($conn, $sql);
while ($row = mysqli_fetch_assoc(result)) {
echo $row['name']. "<br>";
}
mysqli_close($conn);
?>
攻击者可以在搜索框中输入%df%27 or 1=1--
(其中%df
是 GBK 编码下的汉字的一部分字节,%27
是单引号的 URL 编码),这样可能会导致 SQL 注入,进而可能导致跨站脚本攻击(如果 SQL 注入后的数据被用于页面输出)。
二、危害程度比较
一般来说,存储型跨站(Persistent Cross - Site Scripting)危害相对较严重,攻击面也较广。因为它可以将恶意脚本存储在服务器端,当用户访问相关页面时就会触发攻击。此外,反射型跨站(Reflected Cross - Site Scripting)的危害也不小,self - xss 配合一些 csrf 漏洞,也可以达到利用效果。总体来说,企业反射型跨站出现得较多。黑客可以利用 XSS 进行钓鱼,或注入木马、广告链接等,有些还会在主站注入非法网站的链接,对公司声誉造成影响。很多广告联盟等也会利用 XSS 跟踪用户行为,窃取用户数据等,利用跨站请求一些 JSONP 接口获取用户数据。
三、防御措施
(一)输入验证
- 对于所有用户输入,都应该进行严格的验证。例如,在处理用户输入的搜索框内容时:
<?php
$searchTerm = $_GET['search'];
// 验证用户输入是否只包含合法字符
if (preg_match('/^[a-zA-Z0-9 ]+$/', $searchTerm)) {
// 继续后续操作,如查询数据库等
} else {
// 输入不合法,给出错误提示
echo "无效的搜索输入";
}
?>
- 对于可能包含 HTML 标签的输入,如论坛评论等,应该使用专门的 HTML 过滤库进行处理,以去除潜在的恶意脚本。例如,使用 PHP 的 HTMLPurifier 库:
<?php
require_once 'HTMLPurifier.auto.php';
$purifier = new HTMLPurifier();
$userInput = $_POST['comment'];
$cleanedInput = $purifier->purify($userInput);
// 使用净化后的输入进行后续操作,如存储到数据库或显示在页面上
?>
(二)输出编码
- 当将数据输出到 HTML 页面时,应该对数据进行合适的编码,以防止脚本被意外执行。例如,在 PHP 中使用 htmlspecialchars 函数:
<?php
$userData = "This is a <script>alert('XSS');</script> test";
$encodedData = htmlspecialchars($userData);
echo $encodedData;
// 输出将显示为原始文本,而不会执行脚本
?>
- 对于 JavaScript 中的数据输出,也应该进行编码。例如,使用 JavaScript 的 encodeURIComponent 函数:
var data = "This is a <script>alert('XSS');</script> test";
var encodedData = encodeURIComponent(data);
// 在将数据发送到服务器或在页面上使用时,使用编码后的数据
(三)设置合适的 HTTP 头
- 可以通过设置合适的 HTTP 头来增加安全性。例如,设置 Content - Security - Policy 头可以限制页面加载哪些资源以及如何加载它们。以下是一个简单的示例,限制页面只能从同一个域加载脚本:
Content - Security - Policy: script-src'self';
- 还可以设置 X - Frame - Options 头来防止页面被嵌入到其他框架中,从而避免点击劫持等攻击:
X - Frame - Options: SAMEORIGIN;
(四)框架过滤
目前在做一个框架过滤,例如 Java 平台在做 filter,通过 filter 做输入拦截。不过要全部开放使用,可能还需要再观察。公司到一定量级后统一框架还是很难的,在现有基础上如何找到一个权衡点非常重要。
(五)检测层面和主动检查层面实践经验
- 反射型跨站检测:一般反射型跨站比较容易检测。可以通过发送包含特定脚本的请求,并检查响应中是否包含该脚本的执行结果来判断是否存在反射型跨站漏洞。例如,使用工具发送请求:
curl -X GET "http://example.com/?param=<script>alert('XSS');</script>"
如果响应中包含弹出的警告框,则可能存在反射型跨站漏洞。
- DOM 型跨站检测:对于 DOM 型跨站,现在有专门策略去扫描,会模拟 webkit 内核渲染网页并解析 JS,根据执行结果来判断,相对来说误报率还是比较低的。
四、检测工具
kali 里面有集成一些比较知名的检测工具,例如 XSSER 等。这种检测一般是上线前需要进行安全评审的规范环节之一。
五、其他问题及解决方法
(一)快速精准发现 XSS 并降低垃圾数据
在检测 XSS 时用不同语句尝试可能会造成库中存储很多 “脏” 数据。针对这种情况,一般会有专门的扫描账号去进行检测,避免对正常业务的干扰。另外,扫描器有时候还会删除数据,可以做个高危 URL 配置项来避免。
(二)扫描器漏报误报问题
可以把扫描规则策略做成插件式,还可以根据场景优化,缓解误漏报问题。还可以针对检测范围做个基线性的安全检查,对结果做一次判定,误报的加 flag,后续检测中如果一直为误报可加入黑名单。对于 SRC 来说,也可以把外部爆出来但扫描器没有发现的 XSS 构造语句放到扫描器中。
希望通过对 XSS 漏洞的这些介绍,能让大家对其有更深入的了解,在 Web 开发和致力于安全维护中更加重视这个问题。
如果你想了解更多关于安全方面的知识,请关注我们的系列安全小课堂。同时,欢迎在评论区留言分享你在安全领域的希望在评论区留言分享你在安全领域的经验和见解。
请注意,上述代码示例仅用于演示相关概念和原理,实际应用中应根据具体情况进行合理的安全防护措施