[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 请求(使用拦截证书) │
│ ─────────────────────────> │
│ │
│ ⑤ 拦截代理解密请求,重新发起真实请求 │
│ ────────────────────────> │
│ │
│ ⑥ 接收真实响应,解密后重新加密返回客户端 │
│ <───────────────────────── │
│ <─────────────────── │
└─────────────────────────────────────────────────────────────────┘关键技术点
CA 证书注入
- 拦截工具生成自己的根证书
- 客户端必须信任这个根证书
- 代理为每个域名动态生成证书
动态证书生成
python# 伪代码示例 def request(server_name): # 生成该域名的证书 cert = generate_certificate( subject=server_name, ca_private_key=proxy_ca_key, ca_cert=proxy_ca_cert ) return cert双向解密-加密
- 客户端 ↔ 代理:使用代理生成的证书
- 代理 ↔ 服务器:使用服务器真实证书
证书信任机制
系统证书存储位置
| 平台 | 证书存储位置 | 信任范围 |
|---|---|---|
| Windows | 证书管理器 → 受信任的根证书颁发机构 | 全局信任 |
| macOS | Keychain Access → System Roots | 全局信任 |
| Linux | /etc/ssl/certs/ | 全局信任 |
| Android | Settings → Security → Encryption & credentials | 全局信任 |
| iOS | 设置 → 通用 → 关于本机 → 证书信任设置 | 需手动启用 |
证书信任层级
┌─────────────────┐
│ 根 CA 证书 │
│ (Root CA) │
└────────┬────────┘
│ 签发
┌────────▼────────┐
│ 中间 CA 证书 │
│ (Intermediate) │
└────────┬────────┘
│ 签发
┌────────▼────────┐
│ 终端实体证书 │
│ (End-Entity) │
│ 如: *.google.com│
└─────────────────┘mitmproxy 证书安装流程
# 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 深度使用
工具对比
| 工具 | 界面类型 | 优势 | 劣势 |
|---|---|---|---|
| mitmproxy | TUI (终端) | 轻量、脚本化强大 | 学习曲线陡 |
| mitmweb | Web UI | 可视化友好 | 资源占用高 |
| mitmdump | 命令行 | 适合自动化 | 无交互界面 |
| HTTP Toolkit | GUI | 现代美观 | 商业软件 |
| Burp Suite | GUI | 功能全面 | 重量级、付费 |
mitmproxy 基础命令
# 安装
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
# 特点:
- 现代化 GUI 界面
- 自动配置系统代理
- 支持 GraphQL/gRPC
- 内置流量修改器
# 安装:访问 https://httptoolkit.com/ 下载grpcurl - gRPC 调试工具
# 安装
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 describewebsocat - WebSocket 调试
# 安装
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 核心
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()]实用脚本案例
# 案例 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))使用脚本
# 执行脚本
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 欺骗示例
# 启用 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) |
| 并行重放 | 在原请求有效期内快速重发 | 中等(短窗口+检测) |
| 跨会话重放 | 在不同会话中重放 | 困难(会话绑定) |
重放攻击演示
# 使用 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 攻击示例
<!-- 攻击者构造的恶意页面 -->
<!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 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())// 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 机制 │
│ ├─ 服务端去重处理 │
│ └─ 重复请求返回相同结果 │
│ │
└────────────────────────────────────────────────────────────┘防重放实现示例
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. 其他防御措施
安全响应头
# 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 responseSameSite Cookie 属性
# 设置 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实践与思考
实践记录
环境搭建任务
# 任务 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 流量
- [ ] 测试证书绑定的绕过方法
- [ ] 实现一个简单的防重放机制
疑问与思考
已解答
✅ 为什么需要安装 CA 证书?
- HTTPS 使用 TLS 加密,拦截工具需要解密流量
- 通过安装自己的 CA 证书,让客户端信任拦截工具生成的动态证书
- 这是 MITM 拦截 HTTPS 的核心原理
✅ 证书绑定可以完全防止 MITM 吗?
- 证书绑定是有效的防御手段,但不是绝对的
- 攻击者可能通过逆向工程修改客户端代码
- 需要 root/jailbreak 设备才能绕过(如使用 Frida)
✅ mitmproxy 和 Burp Suite 如何选择?
- mitmproxy:轻量、脚本化、适合自动化
- Burp Suite:功能全面、GUI 友好、适合手动渗透测试
- 可以配合使用:Burp 分析 + mitmproxy 自动化
待探索
❓ 如何绕过证书绑定?
- Frida 动态插桩
- 修改 APK/IPA 文件
- 使用 VPN 模式的抓包工具
❓ HTTP/3 (QUIC) 如何拦截?
- QUIC 基于 UDP,传统代理方式不适用
- 需要 Quinn/MsQuic 等专门库
- mitmproxy 对 QUIC 的支持还在发展中
❓ 如何检测自己是否被 MITM?
- 检查证书链是否异常
- 使用 SSL Labs 检测
- 观察网络延迟变化
❓ 企业如何安全地进行流量分析?
- 使用透明代理
- 建立内部 CA 并分发证书
- 实施流量监控策略并告知员工
扩展学习方向
深入 TLS/SSL 协议
- TLS 1.3 握手流程
- 前向保密(Perfect Forward Secrecy)
- 证书透明度(Certificate Transparency)
移动端流量分析
- iOS SSL Pinning Bypass
- Android 证书存储机制
- 移动端抓包工具对比
内网渗透与流量分析
- ARP 欺骗与防御
- DNS 劫持技术
- 内网横向移动中的流量利用
更新日期:2026-02-19