第1章 HTTP接口数据安全威胁分析

Android 应用通过 OkHttp 发送的 HTTP/HTTPS 请求在传输过程中面临多种安全威胁。本章从威胁原理、实现流程、防护策略三个维度剖析四大常见攻击:中间人攻击、重放攻击、数据篡改、敏感信息泄漏,为后续章节的防护实现奠定理论基础。

1.1 中间人攻击(MITM)

原理:攻击者通过 ARP 欺骗、DNS 劫持、伪造证书等手段,在客户端与服务器之间插入代理节点,窃听或篡改双向通信内容。

实现流程:

  1. 攻击者部署伪造 Wi-Fi 热点或劫持网关,使客户端流量经过攻击者主机。
  2. 客户端发起 HTTPS 请求时,攻击者拦截 Server Hello,并用自签名证书代替真实证书与客户端握手。
  3. 攻击者与服务器建立真实 TLS 连接,同时与客户端维持攻击者控制的“伪 TLS”连接。
  4. 所有明文数据在攻击者节点可见并可修改。

防护:使用 HTTPS + 证书固定(Certificate Pinning)、HSTS 预加载、双向认证(TLS 客户端证书)。在 OkHttp 中可通过 CertificatePinner 强制校验公钥。

1.2 重放攻击(Replay Attack)

原理:攻击者捕获一次有效的 API 请求(如登录 、支付确认),在后续时间重复发送,欺骗服务器执行重复操作。

实现流程:

  1. 通过抓包工具(Wireshark / Charles)获取完整 HTTP 请求报文。
  2. 原样重放请求(使用相同 URL、Headers、Body),服务器若未检测重放则视为合法请求。

防护:请求中加入时间戳 + 随机 Nonce,服务器校验时间窗口(通常 ≤60s)且 Nonce 不可重复使用;或使用递增序列号 + HMAC 签名。OkHttp 可通过拦截器自动追加时间戳与 Nonce。

1.3 数据篡改(Tampering)

原理:中间人劫持后直接修改请求或响应体中的业务数据(如转账金额、用户权限)。

实现流程:

  1. 攻击者拦截原始请求,修改 Body 内容(例如将 amount=100 改为 amount=10000)。
  2. 将篡改后的请求转发给服务器,服务器无人察觉。

防护:对请求参数与响应体计算 HMAC-SHA256 签名,密钥仅客户端与服务端共享。OkHttp 拦截器可在 Request 构建时注入签名 Header,并在响应时验证签名。

1.4 敏感信息泄漏(Sensitive Data Exposure)

原理:应用通过 HTTP 明文传输 、密码、身份证号等敏感字段,攻击者通过抓包直接获取。

实现流程:

  1. 客户端使用 HTTP 而非 HTTPS,或 HTTPS 配置错误(如忽略证书验证)。
  2. 攻击者在同一局域网内使用 tcpdump / Charles 捕获流量,敏感信息以明文呈现。

防护:始终使用 HTTPS; 放在 Header 而非 URL Query;响应中不返回完整敏感字段(如身份证只显后四位);使用 @RequestHeader 与 @ResponseBody 加密(课程第 8 章详述)。

1.5 威胁全景图

下图汇总四种攻击的实体关系与攻击路径。

HTTP接口数据安全威胁全景图 中间人攻击 (MITM) 重放攻击 (Replay) 数据篡改 (Tampering) 敏感信息泄漏 攻击者 (Attacker) 客户端 (Client) 服务器 (Server) 拦截/窃听 代理/篡改 说明:四种威胁均通过攻击者节点作用于客户端与服务器之间的通信链路

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 头正确设置,避免缓存命中时跳过签名验证。