0%

关于防止失效授权码被利用情况的思考


1 授权码产生原理思考

很多程序的登录以及重要操作都可能采用“授权码”的方式来进行身份认证,授权码的生成工作大多采用授权码生成器产生,根据当前的时间,使用特定的算法来计算出一组“授权码”,这组授权码如果是一分钟有效,那么仅仅跟精度为分钟的当前时间有关。

输入授权码进行验证的时候,系统首先会根据当前的时间参数使用相同的算法产生一组数字来与输入的授权码比较,二者一致即通过验证。

2 过期授权码利用浅析

一些单机系统,如果是使用授权码的方式登录,考虑到它不需要与服务器进行交互,只能从本次获取时间参数。我们可以尝试使用已失效的授权码,并将当前的系统时间调整到当时的有效时间,很可能就可以通过验证,当然只针对一部分软件,大多数软件应该都采取相应措施来防止这种情况发生,

比如下图展示的这个系统,目前就可以还原上面所描述的场景。

图1、一种采用授权码登录的软件

如何得到一个历史授权码呢,很简单,正常使用的时候,记住授权码以及当前的时间即可。

往往,软件设计的没有想象中那么完善,漏洞一定会有的,使用过期的授权码登录系统,其实只是设法绕过了验证,通过验证之后再把系统时间调整回来,其他的功能并不受影响。

以上是单机版是针对单机系统的软件,他们没有服务器,所以修改本地时间就可以实现目的。

3 更多的思考

如果不是单机系统,软件的时间参数一定会从服务器端调取,这样做的好处很多,可以防止修改系统时间使用过期验证码绕过验证的情况,还可以避免服务器与客户端之间的时钟不同步引起的不能通过验证的情况。

如果它们仍然是通过本地调取时间参数,那过期的验证码真的还是很有利用价值,但那真的是不可原谅,应该当做严重的漏洞来对待,必须修改掉才行。

3.1 失效授权码限制机制

除了从获取时间参数的对象上来做预防,应该还有其他更加严格的控制方法,我目前只想到一种方式:失效授权码限制机制

可以采用“失效授权码限制机制”,在验证码发出后,立刻设置计时器开始倒计时,到了失效时间就将该验证码加到“失效授权码清单”,登录认证的时候首先判断是不是属于失效授权码列表。

该机制下的服务器端发放授权码的流程以及授权码的验证过程示例如下:

1
2
3
4
5
6
7
8
9
st=>start: 开始
e=>end: 发放完成
op1=>operation: 生成授权码
op2=>operation: 发放授权码
op3=>operation: 定时器(等待授权码失效)
op4=>operation: 加入失效授权码列表

st->op1->op2->op3->op4
op4->e
图二、服务器端单次授权码发放流程
1
2
3
4
5
6
7
8
9
st=>start: 开始
e=>end: 下一步操作
cond=>condition: 授权码是否有效
op1=>operation: 输入授权码
op2=>operation: 失效授权码列表

st->op1->cond
cond(yes)->e
cond(no)->op1
图三、授权码验证流程

这种方法可以防止失效授权码的使用,即使有人使用手段修改服务器端的时间也不用担心,因为失效的授权码会被加入到一个列表,相当于黑名单的形式,每次验证前都会先检查当前输入的授权码是否有效,每个授权码最多只能被验证一次。

3.2 “失效授权码限制机制”存在的缺点

当然这也里面也有一个问题,正是“每个授权码最多只能被验证一次”这句话,他可能会影响程序的正常使用,不同的时间产生的授权码一定不同吗?当然不一定。那么一旦出现某个授权码刚好历史有出现过的情况,那么它就不能通过验证。

3.3 “失效授权码限制机制”改进思路及应用价值

首先应该知道不同时间产生相同验证码的概率大小,如果概率极小,可以忽略它的这个缺点,也可以通过改进授权码生成算法的方式来解决,使之产生的授权码出现重复的概率变得非常小。

除此之外,“失效授权码清单”不一定有必要永久保存,因为授权码位数通常是固定的,如果每个授权码仅允许使用一次,那么用尽所有授权码只是时间的问题,当然可以通过增加授权码位数的方式来延长这个时间,但是授权码还是会用尽。可以在“授权码用尽或者即将用尽”这种情况下做出改变,重置“失效授权码清单”,并且更换授权码生成算法。

具体流程如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
st=>start: 开始
e=>end: 完成

sub1=>subroutine: 授权码生成算法调度(更新授权码
生成算法、清空失效授权码清单)

op1=>operation: 授权码生成器(每次不同)
op1.5=>operation: 发放授权码
op2=>operation: 定时器(授权码有效时间)
i2=>inputoutput: 失效授权码清单(授权码生成算法
更新时该清单会被清空)
op5=>operation: 原算法产生下一个
(此步虚动作)
op6=>operation: 新算法生成下一个(此步虚动作)
cod=>condition: 是否需要重置算法

st->sub1->op1->op1.5->op2->i2->cod
cod(no)->op5->op1
cod(yes)->op6->sub1(right)
图四、优化之后的授权码发放流程

如图所示,在“授权码生成器”之前增加了“授权码生成算法调度”环节,当失效授权码被加入到“失效授权码清单”后,程序会判断是否有必要更新授权码生成算法,若无需更换,则继续按原算法产生下一个授权码,若需要更新,则在下一次授权码产生之前更换授权码生成算法,并重置失效授权码清单。

我对软件设计一窍不通,此刻班门弄斧,肯定有更加高明的做法。


秋风木叶
2019-8-19
有您的赞赏,我会更加有动力!