Skip to content

防重放攻击实战

重放攻击指攻击者截获一次合法请求后,原样再次发送以冒充合法调用。A7验证的握手模型内置了两道防线,客户端也可自行加固。

一、服务端已有的防线

1. 时间戳窗口(±300 秒)

每次 InitHandle 都携带 TimeStamp(Unix 秒级)。服务端校验 abs(服务器时间 - TimeStamp) <= 300,超出直接返回 1014 时间戳已过期。这保证了一份截获的请求最多在 5 分钟内可被重放,过期自动失效。

  • 防御效果:超出 5 分钟的重放请求 100% 被拒
  • 前提:客户端服务器时间不能偏差过大。若用户机器时间不准,建议客户端先校时。

2. 签名与密文绑定

Sign = MD5(ApiPassword + TimeStamp + Data)Data 是 RC4 密文。攻击者即便截获请求,没有 ApiPassword(只在 Init 阶段用 AppKey 换一次,且 AppKey 不进业务流量)就无法重新计算签名,因此无法篡改或重新生成请求。

为什么 AppKey 不出现在业务流量里

业务请求通过 X-Api-Password 头或 Data 密文传递,全程不含 AppKey。即使业务流量被抓包,攻击者也拿不到永久凭据,只能复用同一份 5 分钟内的密文。

二、客户端加固建议

一次性随机数(nonce)

当前后端强制校验 nonce。若你的业务对重放极其敏感,可在明文参数中附加一个客户端生成的随机值(如 &Nonce=<uuid>),并在本地维护「已用 nonce 集合」,对重复 nonce 直接丢弃。

python
import uuid
resp = client.call("SingleLogin", {
    "Card": card, "Mac": mac, "Nonce": uuid.uuid4().hex
})

后端不校验 nonce

加入 nonce 仅能防止客户端自身重复发送;后端不会拒绝重复 nonce。真正的服务端重放防护仍依赖时间戳窗口。不要在文档中声称后端做了 nonce 校验。

TLS 证书固定

对高安全场景,可在客户端做证书固定(Certificate Pinning),防止中间人劫持后改包。但这会提高维护成本(证书轮换时需更新固定值)。

不要把 ApiPassword 落盘

ApiPassword 每次启动重新 Init 获取即可。若写入文件,一旦文件泄露,攻击者可构造任意请求直到该 ApiPassword 被开发者重置。

三、常见误区

误区事实
密文是静态的,可永久重放错误。密文绑定 TimeStamp,超过 ±300s 被拒
抓包能拿到 AppKey错误。业务流量不含 AppKey
后端校验了 nonce错误。当前后端未实现 nonce 校验

相关链接

A7验证 · 软件授权与网络验证平台