Web 应用安全¶
图源:项目内既有威胁建模示意图(人工复核:未见 AI 生成痕迹)。当前主图用于从资产、信任边界、攻击者与缓解措施的关系理解 Web 应用安全。
OWASP Top 10/XSS/SQL 注入——建立 Web 应用安全基线与防御意识
📋 本章目标¶
完成本章学习后,你将能够:
- 理解 OWASP Top 10 安全风险
- 掌握 XSS 攻击原理与防护
- 理解 SQL 注入及防护措施
- 掌握 CSRF 防护方法
- 学会安全编码实践
1. OWASP Top 10¶
1.1 OWASP Top 10 (2021)¶
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) 是攻击者设法让浏览器执行原本不应被信任的脚本或脚本片段的风险类别。
XSS攻击流程
════════════
1. 攻击者提交不受信任的脚本内容
┌─────────────────────────────────────────────┐
│ 评论内容: <script>untrustedAction()</script> │
└─────────────────────────────────────────────┘
│
▼
2. 服务器存储(未过滤)
┌─────────────────────────────────────────────┐
│ 数据库: 存储了包含恶意脚本的评论 │
└─────────────────────────────────────────────┘
│
▼
3. 其他用户浏览页面
┌─────────────────────────────────────────────┐
│ 页面渲染: 不受信任脚本在浏览器执行 │
│ 结果可能包括会话滥用、页面篡改或数据窃取 │
└─────────────────────────────────────────────┘
2.2 XSS 类型¶
| 类型 | 说明 | 示例场景 |
|---|---|---|
| 反射型 | 脚本从 URL 参数反射 | 搜索结果页 |
| 存储型 | 脚本存储在服务器 | 评论、帖子 |
| DOM 型 | 脚本在客户端执行 | JavaScript 动态渲染 |
2.3 XSS 防护¶
# ❌ 不安全代码
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 注入是攻击者通过操纵输入,使应用将外部输入误当作 SQL 语句的一部分执行的风险。
SQL 注入风险示意(概念化)
══════════════════════
正常查询:
─────────────────────────
SELECT * FROM users
WHERE username = 'admin' AND password = 'password123'
危险输入形态:
─────────────────────────
username: [构造的控制字符或注释片段]
password: [任意值]
注入后查询:
─────────────────────────
SELECT * FROM users
WHERE username = 'admin' --' AND password = 'anything'
效果: 原有查询语义被破坏,可能导致绕过验证或越权读取
注:这里保留的是概念级示意,不建议把任何攻击样例当成测试模板。安全验证应在授权环境中进行,并优先通过参数化查询、日志审计与单元测试证明修复有效。
3.2 SQL 注入防护¶
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=?"
password_hash = hash_password(password) # 伪代码:实际应使用成熟密码散列方案
cursor.execute(query, (username, password_hash))
# ✅ 安全: 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) 是攻击者诱导用户在已登录状态下执行非预期操作。
CSRF攻击流程
════════════
1. 用户登录银行网站 bank.com
┌─────────────────┐
│ 用户已认证 │
│ Cookie: session │
└─────────────────┘
2. 用户访问攻击者网站 evil.com
┌─────────────────────────────────────────────┐
│ <img src="bank.com/transfer?to=attacker&amount=10000"> │
└─────────────────────────────────────────────┘
3. 浏览器自动携带Cookie发送请求
┌─────────────────────────────────────────────┐
│ 银行服务器收到转账请求 │
│ Cookie有效 → 转账成功 │
└─────────────────────────────────────────────┘
4.2 CSRF 防护¶
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 输入验证¶
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 安全配置清单¶
# 安全配置清单
## HTTPS
- [ ] 强制HTTPS重定向
- [ ] HSTS头启用
- [ ] 证书有效性检查
## Cookie
- [ ] HttpOnly标志
- [ ] Secure标志
- [ ] SameSite=Strict/Lax
## 安全头
- [ ] X-Content-Type-Options: nosniff
- [ ] X-Frame-Options: DENY
- [ ] Content-Security-Policy
- [ ] Referrer-Policy
- [ ] Permissions-Policy(按需)
## 认证
- [ ] 密码强度要求
- [ ] 登录失败限制
- [ ] 多因素认证
- [ ] 会话超时
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-04-03 适用版本:网络安全教程 v2026
⚠️ 核验说明(2026-04-03):本页已于 2026-04-03 按网络安全专题完成复核。由于安全标准、项目版本、术语口径和威胁态势会持续变化,文中涉及 OWASP / NIST / CWE / 法规 / 工具的内容请以官方文档、授权范围和实际环境为准;高风险内容应以防御、检测、加固和合规学习为边界。
