← 返回 Day 94 正文

Day 94 · 图解

Day 094 — 安全编程 · 图解

1. 注入攻击原理

SQL 注入攻击流程:

用户输入:  ' OR '1'='1' --

              ┌──────────────────────────────────────┐
              │        未过滤的输入                     │
              │  "SELECT * FROM users WHERE            │
              │   name='" + input + "' AND pass='xxx'" │
              └──────────────┬───────────────────────┘
                             │
                             ▼
              ┌──────────────────────────────────────┐
              │        恶意 SQL                        │
              │  SELECT * FROM users WHERE             │
              │  name='' OR '1'='1' --' AND pass='xxx'│
              └──────────────┬───────────────────────┘
                             │
                             ▼
              ┌──────────────────────────────────────┐
              │        攻击结果                        │
              │  返回所有用户,绕过认证                   │
              └──────────────────────────────────────┘

防护: 参数化查询
              ┌──────────────────────────────────────┐
              │  SQL: SELECT * FROM users             │
              │       WHERE name=? AND pass=?         │
              │  参数: (input, password)               │
              └──────────────────────────────────────┘
              输入被当作数据,不是代码!

2. 密码存储安全

❌ 不安全的密码存储:

明文存储:
  数据库: password = "my_secret_123"
  数据库泄露 → 所有密码泄露

简单哈希 (无盐):
  数据库: password = sha256("my_secret_123")
  彩虹表攻击 → 秒级反推

✅ 安全的密码存储:

bcrypt:
  盐: 随机生成 (16 bytes)
  哈希: bcrypt(password + salt, rounds=12)
  
  数据库: $2b$12$随机盐+哈希值
  
  优势:
  - 每个密码独立盐 → 彩虹表无效
  - rounds=12 → 每次验证 ~250ms → 暴力破解极慢
  - 专业算法 → 经过安全审计

3. JWT 认证流程

登录流程:
┌────────┐                    ┌────────┐
│  客户端  │                    │  服务器  │
└────┬───┘                    └────┬───┘
     │                             │
     │  1. POST /login             │
     │  {username, password}       │
     │────────────────────────────►│
     │                             │ 2. 验证密码
     │                             │ 3. 生成 JWT
     │  4. 返回 JWT Token          │
     │◄────────────────────────────│
     │                             │
     │  5. GET /api/data           │
     │  Authorization: Bearer JWT  │
     │────────────────────────────►│
     │                             │ 6. 验证 JWT
     │                             │ 7. 检查权限
     │  8. 返回数据                 │
     │◄────────────────────────────│

JWT Token 结构:
┌──────────────────────────────────────────────────────┐
│  Header.Payload.Signature                              │
├──────────────────────────────────────────────────────┤
│  Header: {"alg":"HS256","typ":"JWT"}                  │
│  Payload: {"sub":"123","exp":1700000000}              │
│  Signature: HMAC-SHA256(header.payload, secret)       │
└──────────────────────────────────────────────────────┘

4. 对称 vs 非对称加密

对称加密 (AES):
  同一个密钥用于加密和解密
  
  明文 ──[密钥K]──► 密文 ──[密钥K]──► 明文
  
  优点: 速度快,适合大数据
  缺点: 密钥分发困难
  
非对称加密 (RSA):
  公钥加密,私钥解密
  
  公钥 (公开)          私钥 (保密)
      │                    │
      ▼                    ▼
  明文 ──[公钥]──► 密文 ──[私钥]──► 明文
  
  优点: 安全分发密钥
  缺点: 速度慢,只适合小数据

实际应用: 混合加密
  1. 用 RSA 交换 AES 密钥
  2. 用 AES 加密实际数据
  3. 兼顾安全性和性能

5. 速率限制原理

暴力破解防护:

请求次数: 1  2  3  4  5  6  7  8  9  10
          │  │  │  │  │  │  │  │  │  │
状态:     ✅ ✅ ✅ ✅ ✅ 🚫 🚫 🚫 🚫 🚫
          │                 │
          │                 └── 超过限制,拒绝访问
          └── 5分钟窗口内的尝试次数

实现方式:
┌─────────────────────────────────────────┐
│  IP/用户名 → [尝试记录列表]               │
│                                           │
│  每次登录:                                 │
│  1. 清理过期记录 (>5分钟)                  │
│  2. 检查尝试次数 (<5次?)                   │
│  3. 允许/拒绝                              │
│  4. 记录本次尝试                           │
└─────────────────────────────────────────┘

6. 安全编码检查清单

输入验证:
  ✅ 所有输入都验证
  ✅ 白名单 > 黑名单
  ✅ 长度限制
  ✅ 类型检查

输出编码:
  ✅ HTML 转义 (防 XSS)
  ✅ URL 编码
  ✅ SQL 参数化

认证授权:
  ✅ 密码哈希 (bcrypt)
  ✅ 速率限制
  ✅ Session/Token 管理
  ✅ 最小权限原则

加密:
  ✅ TLS/HTTPS
  ✅ AES-256-GCM
  ✅ RSA-2048+
  ✅ 密钥管理

日志审计:
  ✅ 记录安全事件
  ✅ 不记录敏感数据
  ✅ 监控异常行为