写点什么

APP 防重放实现

用户头像
草原狼
关注
发布于: 2021 年 03 月 31 日

API 重放攻击又称为回放攻击,它会不断的、恶意的重复一个有效的请求,虽然现在有 https 但是 https 是数据加密,却阻止不了防重放攻击,因为攻击者只要盗取到你的 API 请求,不需要去解密数据。这在 app 端更为常见,因为 web 端会有 token 校验等实现,而一些 app 端请求后端请求无法做 token 校验。

那么如何防止防重放呢?最常用的方式就是签名。


签名算法

签名一般分为签名和校验两个步骤:

  1. app 在每次请求时都做签名,将签名结果放到 header 内。

  2. 后端服务(通常是网关)对请求做签名校验,通过则放行,失败则返回 403。


每次请求调用方除了携带正常的请求参数和 header 还需要携带一些用于签名的 header, 常见的有:

X-App-Versionapp 版本
X-Device-Idapp 设备 id
X-Platforma app 设备类型
X-Timestampunix 时间戳 (秒) 时间戳与服务器时间戳相差超过一定时间(60s) 则会失败
X-App-Key业务申请,服务端下发,需要保存在数据库内,客户端切记不能泄露,每一个 appkey 对应一个 appSecret
X-Nonce 随机数,确保在过期时间内,nonce 不会重复。可以用 md5(uuid+timestamp)等算法。
X-Signature 客户端签名结果no
Content-Typeapplication/josn, application/x-www-form-urlencoded
复制代码


用于签名的字符串:

签名字符串:X-Device-Id+X-App-Version+X-Platform+x-Nonce+$RequestMethod+$RequestPath+$RequestArgs+$Body+X-App-Key+X-Timestamp
其中:X-APP-Key: 调用方向被调方申请得到。
RequestMethod: 请求方法
RequestPath: 请求路径,比如 /v1/query
Body: 请求体,其中对于 json 和 form 格式会做不同的处理。对于 application/json 则直接将整个 json 串 base64 字符串。对于application/x-www-form-urlencoded 则首先要将 formData key=value 值按照 key 进行升序排序,按照 key1=value1&key2=value2 方式拼接
RequestArgs: 将 queryArgs key=value 值按照 key 进行升序排序,按照 key1=value1&key2=value2 方式拼接。
复制代码


得到签名字符串后,用 hmacsha256 进行签名。其中 secret 为调用方向被调方申请得到,同样不能泄露。

得到签名字符串,将签名结果放入 header X-Signature 内发送请求即可。


服务端验签具体步骤

服务端获得请求做如下验签动作:假设过期时间为 60s。

  1. 根据 X-App-Key 获取 appSecret  拼接签名字符串获得服务端签名,并与客户端参数 X-Signature 比对,不一致则签名失败。

  2. 获取 X-Timestamp 并与本地时间戳想比较,相差 > 60s 则直接验签失败。

  3. 获取 X-Nonce 查找缓存(redis)是否存在此 nonce,如果没有,则创建此 key,并设置失效时间为 60s( 和 timestamp 失效时间一致),如果有,则认为是重放,签名失败。

  4. timestamp 合法,签名合法,nonce 合法,则请求合法,放行请求。


防重放原理

首先是安全性,由 appKey 与 appSecret 保证,由于 appSecret 不会在网络中传播,所以丢失风险很小。

其次是怎么防重放,将时间戳放入签名内,可以限制签名有效期,即使被劫持,也只能在有效期内进行,无法跨域很长时间进行。利用 nonce 就可以彻底防止防重放了,因为 nonce 生成是在过期时间内确保唯一的。所以每次请求都会不一样。每次请求都会校验 nonce 是否已经使用过。如果使用过就可以认为是一个重放请求,直接拦截在网关层。


发布于: 2021 年 03 月 31 日阅读数: 20
用户头像

草原狼

关注

还未添加个人签名 2019.05.08 加入

还未添加个人简介

评论

发布
暂无评论
APP 防重放实现