Skip to content

[HTTP 调试进阶:流量拦截、修改与重放]

100 天认知提升计划 | Day 4


目录


第一部分:HTTP/HTTPS 拦截原理

HTTP 代理基础

概念说明

HTTP 代理是客户端和服务器之间的中间层,负责转发请求和响应。理解代理工作原理是掌握流量拦截的基础。

代理类型对比

类型工作模式特点适用场景
正向代理客户端 → 代理 → 服务器隐藏客户端 IP科学上网、企业管控
反向代理客户端 → 代理(服务器) → 后端隐藏后端服务器负载均衡、缓存
透明代理流量自动被代理拦截客户端无感知网关监控、内容过滤
拦截代理中间人模式可修改请求/响应调试、测试、渗透

HTTP 代理工作流程

客户端                    代理                    服务器
  │                        │                        │
  │────── GET /api ────────>│                        │
  │                        │────── GET /api ────────>│
  │                        │<───── 200 OK ──────────│
  │<───── 200 OK ──────────│                        │
  │                        │                        │

HTTPS 中间人攻击原理

概念说明

HTTPS 通过 TLS/SSL 加密保护数据,拦截 HTTPS 流量需要使用"中间人攻击"(MITM, Man-In-The-Middle)技术。

HTTPS 拦截完整流程

┌─────────────────────────────────────────────────────────────────┐
│                      HTTPS 拦截流程                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   客户端              拦截代理             服务器               │
│                                                                 │
│  ① 建立连接           ② 伪造证书                               │
│  ──────────>         ──────────>                              │
│                     ──────────>                                │
│                                                                 │
│  ③ 信任拦截代理的 CA 证书                                        │
│  <──────────                                                  │
│                                                                 │
│  ④ 发起 HTTPS 请求(使用拦截证书)                               │
│  ─────────────────────────>                                    │
│                                                                 │
│  ⑤ 拦截代理解密请求,重新发起真实请求                            │
│                     ────────────────────────>                  │
│                                                                 │
│  ⑥ 接收真实响应,解密后重新加密返回客户端                        │
│  <─────────────────────────                                    │
│                     <───────────────────                       │
└─────────────────────────────────────────────────────────────────┘

关键技术点

  1. CA 证书注入

    • 拦截工具生成自己的根证书
    • 客户端必须信任这个根证书
    • 代理为每个域名动态生成证书
  2. 动态证书生成

    python
    # 伪代码示例
    def request(server_name):
        # 生成该域名的证书
        cert = generate_certificate(
            subject=server_name,
            ca_private_key=proxy_ca_key,
            ca_cert=proxy_ca_cert
        )
        return cert
  3. 双向解密-加密

    • 客户端 ↔ 代理:使用代理生成的证书
    • 代理 ↔ 服务器:使用服务器真实证书

证书信任机制

系统证书存储位置

平台证书存储位置信任范围
Windows证书管理器 → 受信任的根证书颁发机构全局信任
macOSKeychain Access → System Roots全局信任
Linux/etc/ssl/certs/全局信任
AndroidSettings → Security → Encryption & credentials全局信任
iOS设置 → 通用 → 关于本机 → 证书信任设置需手动启用

证书信任层级

                 ┌─────────────────┐
                 │   根 CA 证书    │
                 │  (Root CA)      │
                 └────────┬────────┘
                          │ 签发
                 ┌────────▼────────┐
                 │  中间 CA 证书   │
                 │ (Intermediate)  │
                 └────────┬────────┘
                          │ 签发
                 ┌────────▼────────┐
                 │  终端实体证书   │
                 │ (End-Entity)    │
                 │ 如: *.google.com│
                 └─────────────────┘

mitmproxy 证书安装流程

bash
# 1. 启动 mitmproxy,自动生成 CA 证书
mitmproxy

# 2. 证书位置
# macOS: ~/.mitmproxy/mitmproxy-ca-cert.pem
# Windows: %USERPROFILE%\.mitmproxy\mitmproxy-ca-cert.pem
# Linux: ~/.mitmproxy/mitmproxy-ca-cert.pem

# 3. 安装证书(需要管理员权限)
# macOS
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ~/.mitmproxy/mitmproxy-ca-cert.pem

# Linux
sudo cp ~/.mitmproxy/mitmproxy-ca-cert.pem /usr/local/share/ca-certificates/mitmproxy-ca.crt
sudo update-ca-certificates

# Android/iOS: 通过浏览器访问 http://mitm.it 下载

第二部分:核心工具实践

mitmproxy 深度使用

工具对比

工具界面类型优势劣势
mitmproxyTUI (终端)轻量、脚本化强大学习曲线陡
mitmwebWeb UI可视化友好资源占用高
mitmdump命令行适合自动化无交互界面
HTTP ToolkitGUI现代美观商业软件
Burp SuiteGUI功能全面重量级、付费

mitmproxy 基础命令

bash
# 安装
brew install mitmproxy  # macOS
pip install mitmproxy  # 跨平台

# 启动模式
mitmproxy              # TUI 交互界面
mitmweb                # Web 界面 (默认 http://127.0.0.1:8081)
mitmdump -s script.py  # 无界面模式,执行脚本

# 常用参数
mitmproxy -p 8080                    # 指定监听端口
mitmproxy --set block_global=false  # 允许远程连接
mitmproxy -m upstream:https://proxy.example.com:8080  # 上游代理
mitmproxy --showhost                 # 显示 Host 名称

交互界面操作

mitmproxy TUI 快捷键:

导航:
  ?        帮助文档
  q        退出/返回
  g        跳转到最新
  G        跳转到最旧

流量操作:
  Enter    查看请求详情
  Tab      切换请求/响应/详情
  |        筛选流量(支持正则)
  z        清空列表
  Z        清空并重置

拦截:
  i        设置拦截规则
  a        接受请求/响应
  E        编辑请求
  R        重放请求

标记:
  m        标记/取消标记
  M        按标记筛选

拦截规则示例

# 请求拦截
~q          # 拦截所有请求
~q google.com # 拦截特定域名
~q /api/      # 拦截特定路径
~q POST       # 拦截 POST 请求

# 响应拦截
~s           # 拦截所有响应
~s 404       # 拦截 404 响应
~s json      # 拦截 JSON 响应

# 组合条件
~q & ~s      # 请求和响应都拦截
~q POST & ~q /api/user

其他调试工具

HTTP Toolkit

bash
# 特点:
- 现代化 GUI 界面
- 自动配置系统代理
- 支持 GraphQL/gRPC
- 内置流量修改器

# 安装:访问 https://httptoolkit.com/ 下载

grpcurl - gRPC 调试工具

bash
# 安装
brew install grpcurl

# 列出服务
grpcurl -plaintext localhost:9090 list

# 列出服务方法
grpcurl -plaintext localhost:9090 list helloworld.Greeter

# 获取服务描述(proto)
grpcurl -plaintext localhost:9090 describe helloworld.HelloRequest

# 调用 RPC 方法
grpcurl -plaintext \
    -d '{"name": "world"}' \
    localhost:9090 \
    helloworld.Greeter/SayHello

# 反射模式调用
grpcurl -plaintext localhost:9090 describe

websocat - WebSocket 调试

bash
# 安装
brew install websocat
cargo install websocat

# WebSocket 服务器
websocat -s 8080

# WebSocket 客户端
websocat ws://echo.websocket.org

# 转发模式(TCP → WebSocket)
websocat -t ws://server.com --unix-socket /tmp/socket

# 带认证
websocat -H "Authorization: Bearer token" wss://api.example.com

高级脚本编写

mitmproxy 脚本 API 核心

python
from mitmproxy import http, ctx

class Interceptor:
    # 请求拦截
    def request(self, flow: http.HTTPFlow) -> None:
        # 修改请求头
        flow.request.headers["X-Custom"] = "intercepted"

        # 修改请求体
        if flow.request.path == "/api/login":
            ctx.log.warn(f"捕获登录请求: {flow.request.pretty_url}")

        # 添加延迟(模拟弱网)
        # import time
        # time.sleep(0.5)

    # 响应拦截
    def response(self, flow: http.HTTPFlow) -> None:
        # 修改响应
        if "application/json" in flow.response.headers.get("content-type", ""):
            data = flow.response.json()
            data["intercepted"] = True
            flow.response.text = json.dumps(data)

        # 替换响应内容
        if flow.request.path.endswith(".js"):
            flow.response.text = flow.response.text.replace("debug", "release")

# 注册 addon
addons = [Interceptor()]

实用脚本案例

python
# 案例 1: API 录制与回放
class APIRecorder:
    def __init__(self):
        self.recordings = []

    def request(self, flow: http.HTTPFlow):
        if flow.request.path.startswith("/api/"):
            recording = {
                "method": flow.request.method,
                "url": flow.request.pretty_url,
                "headers": dict(flow.request.headers),
                "body": flow.request.text
            }
            self.recordings.append(recording)
            ctx.log.info(f"录制: {flow.request.path}")

    def save(self):
        with open("api_recordings.json", "w") as f:
            json.dump(self.recordings, f, indent=2)

# 案例 2: 自动重放失败请求
class AutoReplay:
    def response(self, flow: http.HTTPFlow):
        if flow.response.status_code >= 500:
            ctx.log.warn(f"服务器错误 {flow.response.status_code}, 5秒后重放...")
            import asyncio
            asyncio.get_event_loop().call_later(5, lambda: flow.request.reply())

# 案例 3: Mock API 响应
class APIMock:
    def response(self, flow: http.HTTPFlow):
        if flow.request.path == "/api/v1/users":
            mock_response = {
                "users": [
                    {"id": 1, "name": "Mock User 1"},
                    {"id": 2, "name": "Mock User 2"}
                ],
                "total": 2
            }
            flow.response = http.Response.make(
                200,  # status
                json.dumps(mock_response),  # body
                {"Content-Type": "application/json"}  # headers
            )

# 案例 4: 接口性能监控
class PerformanceMonitor:
    def __init__(self):
        self.stats = {}

    def request(self, flow: http.HTTPFlow):
        flow.request.timestamp_start = time.time()

    def response(self, flow: http.HTTPFlow):
        duration = time.time() - flow.request.timestamp_start
        path = flow.request.path
        if path not in self.stats:
            self.stats[path] = {"count": 0, "total_time": 0, "max_time": 0}
        self.stats[path]["count"] += 1
        self.stats[path]["total_time"] += duration
        self.stats[path]["max_time"] = max(self.stats[path]["max_time"], duration)

        if duration > 1.0:
            ctx.log.warn(f"慢接口: {path} 耗时 {duration:.2f}s")

    def done(self):
        ctx.log.info(json.dumps(self.stats, indent=2))

使用脚本

bash
# 执行脚本
mitmdump -s script.py

# 指定端口
mitmdump -p 8080 -s script.py

# 同时使用多个脚本
mitmdump -s script1.py -s script2.py

# 向脚本传递参数
mitmdump -s "script.py --arg1 value1"

第三部分:攻防技术与实践思考

攻击技术

1. 中间人攻击(MITM)

攻击场景

  • 公共 Wi-Fi 环境窃听
  • 企业内部网络监控
  • 渗透测试中的流量分析

攻击流程

┌──────────────────────────────────────────────────────────────┐
│                    MITM 攻击流程                              │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  ① 网络层劫持                                               │
│     ├─ ARP 欺骗: 让受害者以为攻击者是网关                    │
│     ├─ DNS 欺骗: 修改域名解析                                │
│     └─ 流量重定向: iptables/路由规则                         │
│                                                              │
│  ② 代理服务器启动                                            │
│     ├─ 监听 8080 端口                                        │
│     ├─ 转发流量到真实服务器                                  │
│     └─ 记录所有请求/响应                                     │
│                                                              │
│ ③ HTTPS 证书欺骗                                            │
│     ├─ 生成伪造 CA 证书                                      │
│     ├─ 为目标域名动态生成证书                                │
│     └─ (理想情况)客户端信任该证书                          │
│                                                              │
│  ④ 流量篡改                                                 │
│     ├─ 注入恶意脚本                                          │
│     ├─ 修改请求参数                                          │
│     └─ 篡改响应内容                                          │
│                                                              │
└──────────────────────────────────────────────────────────────┘

ARP 欺骗示例

bash
# 启用 IP 转发
echo 1 > /proc/sys/net/ipv4/ip_forward

# ARP 欺骗(使用 bettercap)
bettercap -caplet

# bettercap 交互命令
> net.recon on                    # 扫描网络
> set arp.spoof.targets 192.168.1.100
> arp.spoof on                    # 开始 ARP 欺骗
> set http.proxy.ssl true         # 启用 HTTPS 拦截
> http.proxy on                   # 启动 HTTP 代理

2. 重放攻击(Replay Attack)

攻击原理

正常流程:
用户 ──(登录请求)──> 服务器
      <──(返回 Token)──
用户 ──(Token + 购买请求)──> 服务器

重放攻击:
攻击者 ──(复制的购买请求)──> 服务器
         使用相同的 Token、时间戳

重放攻击类型

类型描述防御难度
简单重放直接复制请求重发容易(时间戳+Nonce)
并行重放在原请求有效期内快速重发中等(短窗口+检测)
跨会话重放在不同会话中重放困难(会话绑定)

重放攻击演示

python
# 使用 mitmproxy 录制请求
class ReplayCapture:
    def __init__(self):
        self.captured = []

    def request(self, flow: http.HTTPFlow):
        # 记录支付相关请求
        if "/api/payment" in flow.request.path:
            self.captured.append({
                "url": flow.request.pretty_url,
                "method": flow.request.method,
                "headers": dict(flow.request.headers),
                "body": flow.request.text,
                "cookies": dict(flow.request.cookies)
            })

    def done(self):
        with open("replay_payloads.json", "w") as f:
            json.dump(self.captured, f, indent=2)

# 使用 curl 重放
# 从 replay_payloads.json 中提取请求并重放
curl -X POST 'https://api.example.com/payment' \
     -H 'Content-Type: application/json' \
     -H 'Authorization: Bearer <token>' \
     -d '{"amount": 100, "to": "attacker_account"}'

3. 会话劫持(Session Hijacking)

攻击手段

┌────────────────────────────────────────────────────────────┐
│                   会话劫持方式                              │
├────────────────────────────────────────────────────────────┤
│                                                            │
│  ① Session ID 窃取                                         │
│     ├─ 网络嗅探(HTTP 明文传输)                           │
│     ├─ XSS 攻击(读取 document.cookie)                    │
│     └─ MITM 拦截                                           │
│                                                            │
│  ② Session Fixation                                        │
│     └─ 攻击者强制用户使用已知的 Session ID                 │
│                                                            │
│  ③ CSRF(跨站请求伪造)                                    │
│     └─ 利用用户的已登录状态执行未授权操作                  │
│                                                            │
└────────────────────────────────────────────────────────────┘

CSRF 攻击示例

html
<!-- 攻击者构造的恶意页面 -->
<!DOCTYPE html>
<html>
<head>
    <title>恭喜中奖!</title>
</head>
<body>
    <h1>点击领取奖品</h1>
    <!-- 用户点击时,自动发起转账请求 -->
    <img src="https://bank.com/transfer?to=attacker&amount=10000"
         style="width:1px;height:1px;opacity:0">
</body>
</html>

防御技术

1. 证书绑定(Certificate Pinning / SSL Pinning)

概念说明

证书绑定是防止 MITM 攻击的有效手段,客户端内置服务器的证书或公钥哈希,只与特定的证书通信。

证书绑定类型

类型实现方式优点缺点
证书绑定存储完整证书哈希简单直接证书更新困难
公钥绑定只存储公钥哈希允许证书更新仍需密钥轮换策略
中间 CA 绑定绑定中间证书灵活性高实现复杂

证书绑定实现

python
# Python requests 实现
import requests
from hashlib import sha256

# 服务器的预期公钥指纹
EXPECTED_PIN = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="

def cert_pinning_verify(connection, cert, **kwargs):
    # 提取证书公钥并计算哈希
    pub_key = cert.public_key()
    pub_key_bytes = pub_key.public_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PublicFormat.SubjectPublicKeyInfo
    )
    actual_pin = sha256(pub_key_bytes).digest()

    # 验证是否匹配
    if base64.b64encode(actual_pin).decode() != EXPECTED_PIN:
        raise Exception("Certificate pinning failed!")

# 使用自定义验证
session = requests.Session()
session.mount("https://", CustomAdapter())
swift
// iOS/swift 实现
func urlSession(_ session: URLSession,
                didReceive challenge: URLAuthenticationChallenge,
                completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {

    guard let serverTrust = challenge.protectionSpace.serverTrust,
          let certificate = SecTrustGetCertificateAtIndex(serverTrust, 0) else {
        completionHandler(.cancelAuthenticationChallenge, nil)
        return
    }

    // 验证证书公钥指纹
    let serverCertData = SecCertificateCopyData(certificate) as Data
    let serverCertHash = sha256(serverCertData)

    if pinnedCertHashes.contains(serverCertHash) {
        let credential = URLCredential(trust: serverTrust)
        completionHandler(.useCredential, credential)
    } else {
        completionHandler(.cancelAuthenticationChallenge, nil)
    }
}

2. 防重放攻击机制

多层防御策略

┌────────────────────────────────────────────────────────────┐
│                   防重放攻击层级                            │
├────────────────────────────────────────────────────────────┤
│                                                            │
│  第一层:时间戳验证                                         │
│  ├─ 每个请求携带时间戳                                     │
│  ├─ 服务端验证时间差(如 5 分钟内)                        │
│  └─ 过期请求直接拒绝                                       │
│                                                            │
│  第二层:Nonce(一次性随机数)                              │
│  ├─ 每个请求携带唯一 Nonce                                 │
│  ├─ 服务端记录已使用的 Nonce                               │
│  └─ 重复 Nonce 直接拒绝                                    │
│                                                            │
│  第三层:请求签名                                           │
│  ├─ 使用私钥对请求签名                                     │
│  ├─ 包含时间戳 + Nonce + 请求内容                          │
│  └─ 签名验证失败则拒绝                                     │
│                                                            │
│  第四层:幂等性设计                                         │
│  ├─ 幂等 Key 机制                                          │
│  ├─ 服务端去重处理                                         │
│  └─ 重复请求返回相同结果                                   │
│                                                            │
└────────────────────────────────────────────────────────────┘

防重放实现示例

python
import time
import hmac
import hashlib
from flask import Flask, request, jsonify

app = Flask(__name__)
used_nonces = set()  # 生产环境应使用 Redis

def verify_request(headers, body):
    """验证请求是否为重放"""

    # 1. 检查时间戳(5分钟窗口)
    timestamp = int(headers.get('X-Timestamp', 0))
    if abs(time.time() - timestamp) > 300:
        return False, "Request expired"

    # 2. 检查 Nonce 是否重复
    nonce = headers.get('X-Nonce')
    if nonce in used_nonces:
        return False, "Nonce already used"
    used_nonces.add(nonce)

    # 3. 验证签名
    signature = headers.get('X-Signature')
    expected_sig = hmac.new(
        SECRET_KEY.encode(),
        f"{timestamp}:{nonce}:{body}".encode(),
        hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(signature, expected_sig):
        return False, "Invalid signature"

    return True, "OK"

@app.route('/api/payment', methods=['POST'])
def payment():
    # 获取请求内容
    body = request.get_data(as_text=True)

    # 验证请求
    valid, message = verify_request(request.headers, body)
    if not valid:
        return jsonify({"error": message}), 403

    # 处理业务逻辑
    return jsonify({"status": "success"})

3. 其他防御措施

安全响应头

python
# Flask 安全头配置
@app.after_request
def add_security_headers(response):
    # 防止点击劫持
    response.headers['X-Frame-Options'] = 'DENY'

    # 防止 MIME 类型嗅探
    response.headers['X-Content-Type-Options'] = 'nosniff'

    # 开启 XSS 保护
    response.headers['X-XSS-Protection'] = '1; mode=block'

    # 强制 HTTPS(HSTS)
    response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'

    # CSP(内容安全策略)
    response.headers['Content-Security-Policy'] = "default-src 'self'"

    return response

SameSite Cookie 属性

python
# 设置 Cookie 的 SameSite 属性防止 CSRF
@app.route('/login')
def login():
    resp = make_response('Logged in')
    resp.set_cookie(
        'session_id',
        session_token,
        httponly=True,      # 防止 XSS 读取
        secure=True,        # 只通过 HTTPS 传输
        samesite='Strict'   # 防止 CSRF
    )
    return resp

实践与思考

实践记录

环境搭建任务

bash
# 任务 1: 安装 mitmproxy
brew install mitmproxy
mitmproxy --version

# 任务 2: 生成并安装 CA 证书
mitmproxy
# 访问 http://mitm.it 下载证书

# macOS 安装
sudo security add-trusted-cert -d -r trustRoot \
    -k /Library/Keychains/System.keychain \
    ~/.mitmproxy/mitmproxy-ca-cert.pem

# 任务 3: 配置浏览器代理
# Chrome: 安装 SwitchyOmega 扩展
# Firefox: 设置 → 网络设置 → 手动配置代理
# 代理: 127.0.0.1:8080

# 任务 4: 测试 HTTPS 拦截
# 访问 https://example.com,观察 mitmproxy 是否能解密流量

# 任务 5: 编写拦截脚本
# 创建 test_intercept.py

实践清单

  • [ ] 安装并配置 mitmproxy
  • [ ] 在不同平台安装 CA 证书(macOS/Android/iOS)
  • [ ] 编写一个拦截特定 API 的脚本
  • [ ] 实现一个 API Mock 功能
  • [ ] 录制并重放一组 API 请求
  • [ ] 分析某个应用的 HTTP 流量
  • [ ] 测试证书绑定的绕过方法
  • [ ] 实现一个简单的防重放机制

疑问与思考

已解答

  1. 为什么需要安装 CA 证书?

    • HTTPS 使用 TLS 加密,拦截工具需要解密流量
    • 通过安装自己的 CA 证书,让客户端信任拦截工具生成的动态证书
    • 这是 MITM 拦截 HTTPS 的核心原理
  2. 证书绑定可以完全防止 MITM 吗?

    • 证书绑定是有效的防御手段,但不是绝对的
    • 攻击者可能通过逆向工程修改客户端代码
    • 需要 root/jailbreak 设备才能绕过(如使用 Frida)
  3. mitmproxy 和 Burp Suite 如何选择?

    • mitmproxy:轻量、脚本化、适合自动化
    • Burp Suite:功能全面、GUI 友好、适合手动渗透测试
    • 可以配合使用:Burp 分析 + mitmproxy 自动化

待探索

  1. 如何绕过证书绑定?

    • Frida 动态插桩
    • 修改 APK/IPA 文件
    • 使用 VPN 模式的抓包工具
  2. HTTP/3 (QUIC) 如何拦截?

    • QUIC 基于 UDP,传统代理方式不适用
    • 需要 Quinn/MsQuic 等专门库
    • mitmproxy 对 QUIC 的支持还在发展中
  3. 如何检测自己是否被 MITM?

    • 检查证书链是否异常
    • 使用 SSL Labs 检测
    • 观察网络延迟变化
  4. 企业如何安全地进行流量分析?

    • 使用透明代理
    • 建立内部 CA 并分发证书
    • 实施流量监控策略并告知员工

扩展学习方向

  1. 深入 TLS/SSL 协议

    • TLS 1.3 握手流程
    • 前向保密(Perfect Forward Secrecy)
    • 证书透明度(Certificate Transparency)
  2. 移动端流量分析

    • iOS SSL Pinning Bypass
    • Android 证书存储机制
    • 移动端抓包工具对比
  3. 内网渗透与流量分析

    • ARP 欺骗与防御
    • DNS 劫持技术
    • 内网横向移动中的流量利用

更新日期:2026-02-19

参考资料

官方文档

安全相关

推荐阅读

工具下载

用 ❤️ 和 AI 辅助学习