以“互联网安全新思维”为主题的OWASP2011亚洲峰会在11月8日-9日成功举办。本届大会以“网络安全产品测评”、“OWASP应用安全技术”“业务安全发展新思路”“云安全”等多个角度展开深入的讨论。阿里巴巴集团资深安全专家吴瀚清做了《流行应用的加密算法实现缺陷与利用》的演讲。
吴瀚清,2001年,与朋友共同建立了号称黑客组织的“幻影”。2005年加入阿里巴巴,2008年底加入了阿里云,现在在负责阿里云的云计算安全。
吴瀚清首先介绍到,在渗透测试里面遇到了这种情况(如下图)时,一般都会抓狂。看到一大串,可能是加密或者是数字,我们叫做密文。这些看起来很纷乱的密文是有编码规律的,最常用两种编码方式Base 64和Hex,红色这一串数字是16进制的编码或者字符集。我们把它直接转换成16进制之后可以得到密文,通过解码知道密文到底是什么东西,而不是毫无意义的数字了。
加密算法,密文长度有一定规律,如果使用流密码可以是任意长度,如果看到密文的长度没有任何规律,很可能使用的是流密码,如果是分子组加密算法它的密文是有规律的,比如说8的整数倍或者16的整数倍,它的加密出来之后都变成了分组的整数倍,整出密文的长度就可以猜测出它的加密算法。
如果你知道明文的情况下,尝试改变密文的字节,看密文发生了什么变化,如果密文在一个分子长度之内,比如八字节发生了改变,后一个字节没有改变,很可能使用的ECB,如果明文改变1字节,密文完全改变,可能是别的分组加密模式。
开发者如何看待加密算法,对于他们来说加密算法使用的时候好不好用:
1、加密算法第三方实现Library?在渗透过程中遇到一些密文猜测加密算法,看它什么平台使显得,看Web语言里面有没有比较好用的,公开的第三方的加密实现的library。
2、性能。这决定了大的应用网站决定他们不可能选用强度非常高的加密算法,比如使用交换密钥加密整段密文这种方法肯定不能被接受的。开发者们需要选择高性能的开发算法。
像DES算法可以在一天之内把它的密文破解出来,如果开发者选择了DES算法就是不明智的算法。
3、安全—特指密钥长度。加密算法如何安全?密钥超度越长,越安全。对于他们来说选用加密算法的时候,只会简单选择加密算法的密钥是否足够长,加密算法攻击过程中会有非针对长度的攻击。我在后面会讲到。
开发者常犯的错误:
1、使用哈希算法代替加密算法。
2、哈希算法不适用的场景。
3、使用时间函数代替伪随机数算法。
4、不了解一些密码学攻击,导致使用错误。
加密算法可以分为两种:分组加密算法、流密码。
加密算法有一个概念IV:初始化向量,一次一密,无须保密。
加密模式:ECB、CBC、CFB、OFB、CTR。后三种不是很常见的,ECB是性能最好,也是不安全的。CBC性能和安全性达到一定的程度。
分组长度:Blocksize,分组长度是固定的。
密钥:KEY、须保密、有时对长度有要求。
在密码学里面,针对加密算法的攻击有这么几种方式,就不展开讲了,与今天讲的内容没有太直接的联系,这些东西更多是在密码学里面进行的分类。
攻击分组加密算法,ECB模式,是一种非常简单的加密模式,它将明文分成不同的组,每一组都进行加密使用相同的密钥加密,加密之后出来密文,密文模式又叫电码簿模式。把明文密文交换,密文的分组也会自动的交换,如果攻击者知道明文里面的敏感信息,可以替换密文,从而达到所要的效果,比如说支付的时候付了一块钱,可以改为一百块,用一块钱买到一百块钱的东西。下面这张图片点正是由ECB模式加密的,我们可以看到它隐隐约约渗透出来的一些信息。最右边这张图采取链式的模式,信息就被掩盖了,大量的统计情况下使用ECB的模式是不明确的,不能完全保护你的信息。
CBC模式常见的攻击是Pading Oracle,Pading Oracle它实际上是一种变信道攻击,像盲注一样基于结果的预测,只需要知道揭秘之后结果是不是Pading Oracle正确,就可以推断出算法的实践是不是存在缺陷的。
流密码攻击在Web领域用的最多,因为它的性能非常好。流密码一个字节一个字节加密,密钥长度和明文长度是一样长的,如果不一样长怎么办?把密钥重叠,再逐字节加密。加密结果有一个IV,IV和密钥形成真正用于加密的程序密钥,通过异或操作加密成密文。在流密码里面存在Reused Key Attack,通过一组推导得出红字表示的结论,密文和密文之间异或之后等于明文和明文之间异或,我们在已知三个数据的情况下,就可以推导出已知的。
我们知道PHPWind是国内著名的论坛,他有一个加密的函数使用的非常简单的异或加密,关键的代码是我下面标红的一行。我们就使用这种攻击破解PHPwind验证码,它只有32个字符产生,生成的明文是这样的数据结构,有一个时间戳,再有mdi,再加上时间戳。我们通过网络获取验证码,接下来通过一定的算法把验证码破解出来。它的验证码实际上在Cookie里面设置了加密值,服务端比对加密的串。我们有这样一个思路,已知了先自己构造一下抓一下包,已知明文1就知道密文2,可以推导明文2。我们采用彩虹表就可以辩解出明文什么意思,这张彩虹表要自己做出来,这张彩虹表我们制作起来并不是特别困难,因为它是有时间戳的。这里我贴了一张图,通过了一千多次的训练在886秒里面,我通过一个算法自动化破解了这张验证码的明文值,白色的地方就是破解出来的明文值和验证码是完全一样的。
第二种对于流密码攻击叫做Bit—Flipping Attack。比如说刚才的验证码,验证码里面加入时间戳的目的通过时间对用户提交的验证码进行校验,关键的判断是通过服务器取当今时间再减去cookie验证过的时间是不是大于1800秒,我们自己构造一个超大时间,使得这个时间永不过期,让时间相减的值小于1,这个时间判断永远是真的。我构造了一个时间,计算机里面转换时间是13多少多少,我写了12多少,相减是负数,通过网络请求反馈结果,说明我们验证码是永远通过的。
还可以讲讲Discuz authcode()函数,Discuz authcode()也是用它加密cookie,这个函数相对比前面的函数好一点,它有很多东西保证它的安全。我们对authcode()做了分析,加密的明文什么东西,会把明文进行处理。前十位是时间戳,如果是零的话,这个算法也是正确的,我们可以构造我们时间戳全部是零,然后加密密文。接下来的11—16位,是一个HMAC,是用于防篡改的,接下来是明文。整个用于authcode()函数,生成1的密钥进行加密。相对authcode()比较安全的,IV一次一密,导致无法攻击成功。它使用了HMAC是防篡改的,导致无法构造任意密文。明文我们可以已知的,第二个因素是加密的密钥,密钥是未知的,我们在未知密钥的情况下无法构造出authcode()函数的密文的。但是authcode()存在一个弱点,它的默认当前Discuz!版本中是零,使用穷举法建立IV字典(a—Z0—9),当两次加密IV相同时,加密密钥也相同,在WEP破解中,24bitIV在5小时遍历完,5小时之后IV不得不重复。对于authcode()函数来说,一百多万次以后,把所有的IV遍历,IV不得不重复,不得不还原所有的明文。
POC是有两个2626、2630,我通过crack算法破解Cipher2加密之后,我希望它的结果和2630是一样的,最后的计算结果收集了49000多对Keys,花了64秒时间成功计算出了它的明文是2630,authcode()函数存在这个弱点,这个漏洞是Discuz还不知道。PHP的我已经告诉他了,因为我们已经收购他了。
收集这么多密钥比较困难的,主要困难在网络延时上面,通过不停发包,发网络请求收IV。有一个小技巧叫做Birthday Attack,3人中任意2人生日在特定一天(如11.8号)生日概率7.9%,如果任意2人生日相同,30个人里面接近70%。我们设计抓取IV的时候就可以取巧了,通过不断比对所有IV重复性来确定,来快速抓取相同的IV,这并是只存在于理论上的攻击,我分别用两个程序抓IV,很快就发现非常多重复的IV,只要出现重新的IV,秋收可以还原明文了,攻击条件就达成了。
如何攻击authcode(),可以遍历IV,找到相同的IV从而攻击成功。如果在互联网的开源的Web应用里面,你找到了它的加密算法存在缺陷,如果以前的安全者找到了类似的漏洞,PHPCMS cookie注射,通过构造明文注射,使用加密函数之后就可以进行cookie注射。今天的互联网特别是开源软件里面,可能存在非常多这样的问题。
最终留下一些开发建议:不要使用ECB模式、不要使用流密码;推荐使用CBC模式的AES—256或者Blowfish;不要使用相同的KEY做不同的事情;要注意IV的随机性;要使用HMAC—SHA512代替MD5。