欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

防重放

最编程 2024-07-27 16:14:44
...

使用场景 :

当系统需要与云平台进行对接时,常常会使用api鉴权对权限进行鉴定,我们使用的api鉴权方式即为aksk鉴权,简单而言就是通过签名验证是否具有权限。

假设 :

AKSK鉴权并非该帖子的主题,先略过,假设目前组件与云平台都存在一个对称加密的密匙,且组件内提供了一些API给云平台进行调用。

为什么需要防重放 :

当云平台需要调用组件的api时,需要API鉴权。鉴权方案大概为 : 

云平台 :

1)  云平台生成一个随机数,将随机数与api参数一起进行哈希然后利用秘钥进行加密(类似于签名)生成一个code,然后将随机数,api参数和code发送给客户端。

2) 经过SSL加密到达服务端

组件 :

1) 从SSL取得解密的数据

2) 将随机数与api参数一起进行哈希然后利用秘钥进行加密(类似于签名)生成另一个code与收到的code进行比对。

问题 : 虽然上述方案看起来很严谨,又是哈希又是加密还有SSL保护,但仍然存在漏洞。

例如 : 攻击方不一定需要知道你的秘钥是什么,他只需要将你的包再次发送给客户端,他就可以获取到api的返回结果。

如若是获取root用户当前密码或者重置root用户当前密码的api。那么可能直接对方就获取到了root权限。

防重放方案v1 : 

方案 : 

其实很简单,在服务器端存储一个随机数集,每个随机数只能使用一次,组件在1,2步骤中加一个步骤 : 查询随机数是否处于随机数集中,如若存在,返回重复随机数错误,如若不存在将其则加入随机数集。

为什么方案有效 :

由于会进行签名检验,故而如若你抓到包,然后更改为一个未曾使用过的随机数 + api参数 + code,即使api参数不变,code也不可能与随机数 + api参数的签名结果相同。

新的问题 :

由于有些api可能是间隔时间访问,例如 : 获取组件的运行状态。

如若不清除随机数集 那么势必会导致 随机数 不够用,由于查询 随机数 时间过长导致api访问失败。甚至 磁盘被写满(假设随机数足够长)。

防重放方案v2 :

方案 :

随机数集中的随机数具有有效期,且定期清除。

避免的问题 :

定期清除避免v1的几乎所有问题,如若设置一个月甚至半年的有效期,也不存在太大的安全隐患(一般没人留着包等半年后去攻击你,但不排除这种可能性)。

问题 :

查询时间长,占用磁盘的旧问题并未完全解决,如若遇到高频率访问的api完全有可能重现这些问题。

新问题 : 有效期后的重放攻击无法避免。

防重放方案v3 :

云平台 :

1)  云平台生成一个随机数 rand,记录当前时间time ,将rand + time + api参数一起进行哈希然后利用秘钥进行加密(类似于签名)生成一个code,然后rand + time + api参数 + code发送给客户端。

2) 经过SSL加密到达服务端

组件 :

1) 从SSL取得解密的数据

2) 检测 time 与服务端当前时间是否超过 2 * TTL。

3) 将rand + time + api参数一起进行哈希然后利用秘钥进行加密(类似于签名)生成另一个code与收到的code进行比对。

4) 遍历检测当前随机数集是否存在超出有效期(2*TTL)的随机数,如若有则删除。

3) 遍历检测当前随机数集是否存在rand。

4) 将rand和time写入随机数集。

5) 提供服务并返回结果。

原理 : 

1) 利用签名保证了 time 和 rand 的可靠性。

2) 利用 time 排除了time < server_time 和 time > server_time + 2*TTL 的包。

3) 利用 具有有效期的随机数集 保证了 在 server_time  <= time <= server_time + 2*TTL 内的包 rand 不重复。

优势 : 

维护的 具有有效期的随机数集 小,所以不会因为鉴权导致更高的时间与空间上的过度浪费,安全。