第1章 HTTP接口数据安全威胁分析
Android 应用通过 OkHttp 发送的 HTTP/HTTPS 请求在传输过程中面临多种安全威胁。本章从威胁原理、实现流程、防护策略三个维度剖析四大常见攻击:中间人攻击、重放攻击、数据篡改、敏感信息泄漏,为后续章节的防护实现奠定理论基础。
1.1 中间人攻击(MITM)
原理:攻击者通过 ARP 欺骗、DNS 劫持、伪造证书等手段,在客户端与服务器之间插入代理节点,窃听或篡改双向通信内容。
实现流程:
- 攻击者部署伪造 Wi-Fi 热点或劫持网关,使客户端流量经过攻击者主机。
- 客户端发起 HTTPS 请求时,攻击者拦截 Server Hello,并用自签名证书代替真实证书与客户端握手。
- 攻击者与服务器建立真实 TLS 连接,同时与客户端维持攻击者控制的“伪 TLS”连接。
- 所有明文数据在攻击者节点可见并可修改。
防护:使用 HTTPS + 证书固定(Certificate Pinning)、HSTS 预加载、双向认证(TLS 客户端证书)。在 OkHttp 中可通过 CertificatePinner 强制校验公钥。
1.2 重放攻击(Replay Attack)
原理:攻击者捕获一次有效的 API 请求(如登录 、支付确认),在后续时间重复发送,欺骗服务器执行重复操作。
实现流程:
- 通过抓包工具(Wireshark / Charles)获取完整 HTTP 请求报文。
- 原样重放请求(使用相同 URL、Headers、Body),服务器若未检测重放则视为合法请求。
防护:请求中加入时间戳 + 随机 Nonce,服务器校验时间窗口(通常 ≤60s)且 Nonce 不可重复使用;或使用递增序列号 + HMAC 签名。OkHttp 可通过拦截器自动追加时间戳与 Nonce。
1.3 数据篡改(Tampering)
原理:中间人劫持后直接修改请求或响应体中的业务数据(如转账金额、用户权限)。
实现流程:
- 攻击者拦截原始请求,修改 Body 内容(例如将
amount=100改为amount=10000)。 - 将篡改后的请求转发给服务器,服务器无人察觉。
防护:对请求参数与响应体计算 HMAC-SHA256 签名,密钥仅客户端与服务端共享。OkHttp 拦截器可在 Request 构建时注入签名 Header,并在响应时验证签名。
1.4 敏感信息泄漏(Sensitive Data Exposure)
原理:应用通过 HTTP 明文传输 、密码、身份证号等敏感字段,攻击者通过抓包直接获取。
实现流程:
- 客户端使用 HTTP 而非 HTTPS,或 HTTPS 配置错误(如忽略证书验证)。
- 攻击者在同一局域网内使用 tcpdump / Charles 捕获流量,敏感信息以明文呈现。
防护:始终使用 HTTPS; 放在 Header 而非 URL Query;响应中不返回完整敏感字段(如身份证只显后四位);使用 @RequestHeader 与 @ResponseBody 加密(课程第 8 章详述)。
1.5 威胁全景图
下图汇总四种攻击的实体关系与攻击路径。
1.6 安全防护策略对比
| 威胁类型 | 攻击原理 | 常见工具 | 防护技术 |
|---|---|---|---|
| 中间人攻击 | 伪造证书/ARP劫持,建立伪TLS连接 | mitmproxy, Charles, Wireshark | HTTPS + 证书固定 (OkHttp CertificatePinner) |
| 重放攻击 | 捕获请求报文后重复发送 | Burp Suite Repeater, Postman | 时间戳 + Nonce + HMAC 签名 |
| 数据篡改 | 中间人修改请求/响应体 | mitmproxy脚本, Fiddler AutoResponder | 请求/响应体 HMAC 签名校验 |
| 敏感信息泄漏 | 明文传输/密码等 | tcpdump, Wireshark | 全站 HTTPS;敏感字段强制加密/遮蔽 |
1.7 OkHttp环境下的威胁验证
通过配置 OkHttp 代理暴露抓包场景,理解中间人攻击的可操作性。生产环境禁止保留代理设置。
// 错误示范:允许代理(仅用于调试)
OkHttpClient client = new OkHttpClient.Builder()
.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("192.168.1.100", 8888)))
.build();
// 正确示范:生产环境移除代理,启用证书固定
CertificatePinner pinner = new CertificatePinner.Builder()
.add("api.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.build();
OkHttpClient secureClient = new OkHttpClient.Builder()
.certificatePinner(pinner)
.build();
1.8 调试与抓包分析
使用 Charles 抓包验证威胁:
// 1. 在PC启动Charles,启用SSL Proxying
// Proxy -> SSL Proxying Settings -> Add Host: api.example.com Port: 443
// 2. 手机设置WiFi代理为PC地址:8888
// 3. 安装Charles根证书到Android系统信任凭据(需root或adb push)
// 4. 应用发送请求,Charles展示解密后的明文请求/响应
若应用启用了证书固定(如上述 CertificatePinner),抓包工具将无法解密,HTTP请求会抛出 SSLHandshakeException。
1.9 常见错误与避坑
- 未验证主机名:使用自定义
HostnameVerifier返回 true,导致所有证书均通过,攻击者可轻松伪造。 - 重放检测依赖单一时间戳:若客户端与服务器时间不同步,时间窗口失效。建议配合 Nonce 唯一性检查。
- 签名密钥硬编码在客户端:攻击者反编译即可获取密钥,应使用密钥派生或动态下发(课程第9章详述)。
- 忽略响应签名:只保护请求不保护响应,攻击者仍可篡改服务端返回数据。
1.10 性能与稳定性考量
- 签名计算:HMAC-SHA256 在 OkHttp 拦截器中每次请求仅增加约 0.1ms(现代设备)。建议使用异步计算避免阻塞主线程。
- 时间戳同步:应用启动时与 NTP 服务器校时,避免因本地时间偏差导致重放检测误判。
- 证书固定策略:固定公钥而非证书,支持证书轮换;固定多个备用公钥(backup pin)以应对证书到期。
- 缓存影响:签名需要基于完整请求体计算,若使用 OkHttp 缓存,需确保签名的
Cache-Control头正确设置,避免缓存命中时跳过签名验证。