业务与安全,程序员思维的两面

 

前些天遇到了一个关于Bleinchenbacher padding oracle攻击的问题,问题本身不是很难,但是比较有趣。其乐趣在于,一来我是第一次接触密码学上的攻防,需要在协议实现层面去分析漏洞,二来是事后做了一些情不自禁的思考。

这个事情,还是得从原理说起。

RSA的延展性

延展性是密码算法的一种性质。如果一段密文经过处理后得到另外一段密文,而新的密文所对应的明文,与原明文具有确定的关系,则这种算法具有延展性。

RSA就具有这种性质。对于RSA,有这样的推导式:


也就是说,如果一个攻击者拿到一个密文E(m),他不知道对应的明文m,但是他可以很容易构造出m的整数倍所对应的密文E(mt)。

为了弥补RSA的延展性,在实际应用中,RSA加密都是经过填充的,常用的填充方式有OAEP 和 PKCS#1。今天讨论的问题,涉及到PKCS#1填充,这种填充方式中,要加密的数据M被填充成于RSA模数n一样的长度。M经过填充成为m,m有如下格式:

0x00 0x02 [一些非0字节] 0x00 [这里是M]

且总长度等于n的长度。

填充后,攻击者构造出的mt很可能是不符合这个填充规则的,因此解密者可以识别这种攻击。

Bleinchenbacher攻击原理

这种填充,使攻击者不能对任意t,直接构造出E(mt)。然而,在碰撞攻击的场景下,却暗藏另外的隐患。在一些密码协议的实现中,解密者会校验填充的格式,如果格式正确,则继续正常业务流程;如果格式校验失败,则有可能是另外一种行为(例如没有任何响应,或者响应一个错误报文),这种行为上的差异,给了碰撞攻击者一个启示:这次的mt,格式上是正确的。

攻击者依次尝试各种t,在一定的概率中,mt会符合这个格式,这个概率是2的负15次方到2的负17次方之间(解密后头两个字节恰好是0x0002且后边有一个0字节的概率)。攻击者根据对方的行为,得知自己获得了一次成功,即mt符合PKCS#1格式,这就是所谓的一个启示。这个启示之所以有用,是因为PKCS#1格式具备数学上的意义,即符合该格式的数,取值范围在 [0x0002000…,0x0003000…)区间内。由于t为已知,可以计算出一个m的取值范围。攻击者重复这样的尝试,不断得到关于m取值范围的启示,直到得到唯一的m。这当然需要很多碰撞,据说需要一百万次,当然也有人多攻击做过优化,可以再少一些。无论如何,这种思路指导下的碰撞,比野蛮碰撞,效率高太多了,变得实际可行。

这个攻击的思想,并不是很复杂。

业务、安全,程序员思维的两面

想要避免这个漏洞,其实也很简单,那就是不要给攻击者以启示。这这种避免攻击的方法实在是很简单,即便是在陈旧的代码上,也很容易实现。然而,这个可以很简单就避免的漏洞,却实实在在发生了。

为什么呢?因为协议的实现者,是个业务程序员,实现业务的思路通常是一旦出现异常情况就跑路,代码能返回就返回,这个业务我不要了,好一点的就是增加一些日志告警一类的定位手段。然而在一些场景中,却不是这样,例如今天讨论的例子。

我们在编码时,有时会强调防御式编程,对外部的输入做很强的校验。然而这种做法让程序员的思路停留在代码上,如果程序员脑海中只有代码,那么他的视野就缩小了,他的注意力蜷缩在了一个CPU上,他可能会识别并规避来自外部的所有的异常,保证自己的设备不会出崩溃,不会资源泄露,但是他很难意识到自己代码的行为特点会被别人利用。

在代码中对外部输入做很多检查当然是必要的,然而这是不够的,做检查只能发现一些异常的输入,处理这些异常则不能将视野局限在代码上。事实上,我觉得程序员的注意力放在报文交互上时,他很容易察觉到一些特殊行为的不妥之处(况且他还是一个编写加密协议的程序员,应该有些密码学的底子),则这种漏洞就不会出现。也就是说,我确实建议对外部输入多做校验,我同时还建议,在处理这些异常的时候,不能只局限于本地的代码实现,应该考虑更多的影响性。

上边的建议,是给个体的程序员,那么管理者应该做些什么呢?除了增强团队的能力和责任心,我没有很好的建议。貌似白盒的代码扫描和黑盒的漏洞扫描,都不见得一定能避免这种问题,也就是说很难通过一个套路来避免问题。开展安全review一类的活动,或许会起到比较好的作用,然而在开发团队中,通常是业务程序员居多,而安全人员较少,这类活动不太容易开展,最终还是落在增强业务程序员安全意识上。

 

 

参考资料:

https://crypto.stackexchange.com/questions/12688/can-you-explain-bleichenbachers-cca-attack-on-pkcs1-v1-5

https://en.wikipedia.org/wiki/Malleability_(cryptography)

http://www.edu.cn/xxh/media/yjfz/xslt/201706/t20170613_1527553.shtml

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值