Web应用安全¶
OWASP Top 10/XSS/SQL注入——保护Web应用免受攻击
📋 本章目标¶
完成本章学习后,你将能够:
- 理解OWASP Top 10安全风险
- 掌握XSS攻击原理与防护
- 理解SQL注入及防护措施
- 掌握CSRF防护方法
- 学会安全编码实践
1. OWASP Top 10¶
1.1 OWASP Top 10 (2021)¶
Text Only
OWASP Top 10 - 2021
═══════════════════
┌──────┬────────────────────────────────────────┬───────────┐
│ 排名 │ 漏洞类型 │ 风险等级 │
├──────┼────────────────────────────────────────┼───────────┤
│ A01 │ 访问控制失效 (Broken Access Control) │ 高 │
│ A02 │ 加密失败 (Cryptographic Failures) │ 高 │
│ A03 │ 注入 (Injection) │ 高 │
│ A04 │ 不安全设计 (Insecure Design) │ 中高 │
│ A05 │ 安全配置错误 (Security Misconfiguration)│ 中高 │
│ A06 │ 易受攻击的组件 (Vulnerable Components) │ 中高 │
│ A07 │ 认证失败 (Authentication Failures) │ 高 │
│ A08 │ 软件和数据完整性失败 │ 高 │
│ A09 │ 日志监控失败 (Logging Failures) │ 中 │
│ A10 │ 服务器端请求伪造 (SSRF) │ 中高 │
└──────┴────────────────────────────────────────┴───────────┘
2. XSS攻击¶
2.1 什么是XSS¶
跨站脚本攻击 (XSS) 是攻击者向Web页面注入恶意脚本的攻击方式。
Text Only
XSS攻击流程
════════════
1. 攻击者注入恶意脚本
┌─────────────────────────────────────────────┐
│ 评论内容: <script>steal(cookie)</script> │
└─────────────────────────────────────────────┘
│
▼
2. 服务器存储(未过滤)
┌─────────────────────────────────────────────┐
│ 数据库: 存储了包含恶意脚本的评论 │
└─────────────────────────────────────────────┘
│
▼
3. 其他用户浏览页面
┌─────────────────────────────────────────────┐
│ 页面渲染: 恶意脚本在用户浏览器执行 │
│ Cookie被盗 → 攻击者获取用户会话 │
└─────────────────────────────────────────────┘
2.2 XSS类型¶
| 类型 | 说明 | 示例场景 |
|---|---|---|
| 反射型 | 脚本从URL参数反射 | 搜索结果页 |
| 存储型 | 脚本存储在服务器 | 评论、帖子 |
| DOM型 | 脚本在客户端执行 | JavaScript动态渲染 |
2.3 XSS防护¶
Python
# ❌ 不安全代码
def unsafe_display(user_input):
return f"<div>{user_input}</div>"
# ✅ 安全代码 - 输出编码
import html
def safe_display(user_input):
return f"<div>{html.escape(user_input)}</div>"
# ✅ 安全代码 - Content Security Policy
# HTTP响应头设置:
# Content-Security-Policy: default-src 'self'; script-src 'self'
# ✅ 安全代码 - HttpOnly Cookie
# Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Strict
3. SQL注入¶
3.1 什么是SQL注入¶
SQL注入是攻击者通过构造恶意输入来操纵数据库查询的攻击。
Text Only
SQL注入示例
════════════
正常查询:
─────────────────────────
SELECT * FROM users
WHERE username = 'admin' AND password = 'password123'
攻击者输入:
─────────────────────────
username: admin' --
password: anything
注入后查询:
─────────────────────────
SELECT * FROM users
WHERE username = 'admin' --' AND password = 'anything'
效果: 注释掉密码验证,直接登录admin账户
3.2 SQL注入防护¶
Python
import sqlite3
# ❌ 不安全: 字符串拼接
def unsafe_login(username, password):
query = f"SELECT * FROM users WHERE username='{username}'"
cursor.execute(query)
# ✅ 安全: 参数化查询
def safe_login(username, password):
query = "SELECT * FROM users WHERE username=? AND password=?"
cursor.execute(query, (username, hashed_password))
# ✅ 安全: ORM框架
from sqlalchemy.orm import Session
from models import User
def orm_login(db: Session, username: str):
return db.query(User).filter(User.username == username).first()
# ✅ 其他防护措施
"""
• 使用最小权限原则配置数据库账户
• 输入验证和白名单
• 使用存储过程
• WAF防护
"""
4. CSRF攻击¶
4.1 什么是CSRF¶
跨站请求伪造 (CSRF) 是攻击者诱导用户在已登录状态下执行非预期操作。
Text Only
CSRF攻击流程
════════════
1. 用户登录银行网站 bank.com
┌─────────────────┐
│ 用户已认证 │
│ Cookie: session │
└─────────────────┘
2. 用户访问攻击者网站 evil.com
┌─────────────────────────────────────────────┐
│ <img src="bank.com/transfer?to=attacker&amount=10000"> │
└─────────────────────────────────────────────┘
3. 浏览器自动携带Cookie发送请求
┌─────────────────────────────────────────────┐
│ 银行服务器收到转账请求 │
│ Cookie有效 → 转账成功 │
└─────────────────────────────────────────────┘
4.2 CSRF防护¶
Python
from flask_wtf.csrf import CSRFProtect
# ✅ 方法1: CSRF Token
csrf = CSRFProtect(app)
# 前端表单
# <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
# ✅ 方法2: SameSite Cookie
# Set-Cookie: session=abc; SameSite=Strict
# ✅ 方法3: 验证Referer头
def verify_referer(request):
referer = request.headers.get('Referer', '')
if not referer.startswith('https://mysite.com'):
raise ValueError("Invalid referer")
# ✅ 方法4: 双重Cookie验证
def double_submit_cookie(request):
cookie_token = request.cookies.get('csrf_token')
header_token = request.headers.get('X-CSRF-Token')
return cookie_token == header_token
5. 安全编码实践¶
5.1 输入验证¶
Python
import re
from pydantic import BaseModel, EmailStr, constr # Pydantic数据验证模型
# ✅ 使用数据验证框架
class UserInput(BaseModel):
username: constr(min_length=3, max_length=20, pattern=r'^[a-zA-Z0-9_]+$')
email: EmailStr
age: int = None
class Config:
# 拒绝额外字段
extra = 'forbid'
# ✅ 白名单验证
ALLOWED_FILE_TYPES = {'jpg', 'png', 'gif'}
def validate_file_type(filename):
ext = filename.rsplit('.', 1)[-1].lower() # 负索引:从末尾倒数访问元素
if ext not in ALLOWED_FILE_TYPES:
raise ValueError(f"Invalid file type: {ext}")
return ext
5.2 安全配置清单¶
Text Only
# 安全配置清单
## HTTPS
- [ ] 强制HTTPS重定向
- [ ] HSTS头启用
- [ ] 证书有效性检查
## Cookie
- [ ] HttpOnly标志
- [ ] Secure标志
- [ ] SameSite=Strict/Lax
## 安全头
- [ ] X-Content-Type-Options: nosniff
- [ ] X-Frame-Options: DENY
- [ ] Content-Security-Policy
- [ ] X-XSS-Protection
## 认证
- [ ] 密码强度要求
- [ ] 登录失败限制
- [ ] 多因素认证
- [ ] 会话超时
6. 面试题精选¶
Q1: 如何防止XSS攻击?¶
参考答案: 1. 输出编码:对用户输入进行HTML编码 2. CSP策略:限制脚本来源 3. HttpOnly Cookie:防止Cookie被JS读取 4. 输入验证:过滤特殊字符
Q2: 什么是参数化查询?为什么重要?¶
参考答案: 参数化查询使用占位符代替直接拼接用户输入,数据库引擎会将参数视为数据而非SQL代码,从而防止SQL注入。
Q3: 如何防护CSRF攻击?¶
参考答案: 1. CSRF Token验证 2. SameSite Cookie属性 3. 验证Referer头 4. 关键操作要求二次确认
7. 学习检查清单¶
完成本章学习后,请确认你能够:
- 列出OWASP Top 10主要漏洞
- 解释XSS攻击原理和防护方法
- 实现参数化查询防止SQL注入
- 配置CSRF Token防护
- 应用安全编码最佳实践
参考资料¶
最后更新日期:2026-02-17 适用版本:网络安全教程 v2026
