详解ASP.NET的最新安全漏洞,Padding Oracle攻击原理及其他
微软在9月17日中午正式对外公布了ASP.NET平台下的安全漏洞,即Microsoft Security Advisory (2416728)。
SecurityFocus上已将此漏洞定义成了"Design Error",那么微软一开始的设计就是错误的,为什么这么说呢?且待我们慢慢来分析。
昨天在园友辰的一篇博文:对ASP.NET的最新安全漏洞进一步跟进说明中也看到了对此问题的详细追踪,但上午也只是粗粗浏览,下午细看时总觉文中有些地方略显含糊,所以晚上也就顺带查了些资料,略有所得,不敢独享,遂成此文!
微软的态度
查看了许多微软官方的说明文档,解释的都比较简单,当然对于这个比较大的安全漏洞,不管是出于商业角度的考虑还是对现有.NET架构网站的保护,我们都暂且不去谈论它,但我想攻防该有的一条策略就是:知己知彼,百战不殆!
首先,比较长的一篇文章就是ScottGu的这篇:Important: ASP.NET Security Vulnerability。
在这篇文章中,其主要谈及了此漏洞的影响,简单提及了一下此漏洞产生的原因,下面就是微软教科书式的解决方案了。
这个解决方案有两个注意点:
1:公布了一段vbs,没细看,我想应该是一段检测web.config文件是否添加了customErrors节及是否配置正确的代码;
2:在错误页面中添加的一段代码,我先贴出来,看了下面的分析,我想你就该理解那段代码什么意思了。
2 {
3 byte[] delay = new byte[1];
4 RandomNumberGenerator prng = new RNGCryptoServiceProvider();
5 prng.GetBytes(delay);
6 Thread.Sleep((int)delay[0]);
7 IDisposable disposable = prng as IDisposable;
8 if (disposable != null) { disposable.Dispose(); }
9 }
当然,在这里你还可以看到一些类官方的讨论。
什么叫Padding Oracle
在ScottGu的文章中也提到了Padding Oracle,"......, there is a vulnerability in ASP.NET which acts as a padding oracle"。
首先得承认,padding和Oracle的确太迷惑人了,css+数据库,还挺挑战想象力的。
本人也想不出太好的中文翻译,就直译成了"附加断言"(oracle: 神谕、预言),还望各位指正。
好了,我们来看看Padding Oracle到底是什么。
在ASP.NET中设计ViewState等加密字符串时,在加密算法中,当提交一个文本(ciphertext)去加密后,加密函数将返回是否成功,如返回valid或invalid。
那么攻击者使用不同的值去提交,并捕获返回的值,对每次返回的值进行分析,再纠正,重新提交,就这样解密出原文。那么需要多少次可以解密出到明文呢?答案是:128*N,N是这段密文的字节数,所以也就有了博友辰文章中提到的: 这个过程100%成功而且只需要30分钟。(当然,不会是100%成功的!)
原文是这样的:
The attack works under the assumption that the attackers can intercept padded messages encrypted in CBC mode, and have access to the aforementioned padding oracle. The result is that attackers can recover the plaintext corresponding to any block of ciphertext using an average of 128 * b oracle calls, where b is the number of bytes in a block.
理解有失偏颇的,提醒下。
那么在博友辰的文章中还提到了:这个问题不仅仅存在于asp.net,而且还有java等。
这个背景在于:在隐藏字段(如ViewState),cookies,请求参数中,当加密成BASE64字符串时都涉及到这个漏洞,而在一些Java框架,如JavaServer Face中也设计了ViewState的东西,所以才有了上面的结论。
如何攻击
其实此漏洞的利用在2002年的Eurocrypt会议中已经被提及过了,可以去BlackHat网站下载PDF查看,本人上文的许多分析也提炼自此文档。
Then we decode each Base64 string found. If the result looks random, and its length is a multiple of common block cipher sizes, i.e. 8, 16 or 32 bytes, then there’s a good chance that it is a ciphertext. We also look for common separators, i.e. --, | or :, which are often used to separate IV, ciphertext, or MAC. Then we replace a byte in the last block of the ciphertext by a random value, then send it back to the target, and see what changes in the response. If there is an error message, then there’s a high chance that this is a Padding Oracle.
此段很明了地说明了测试是否可破解的方法。
每次替换掉最后一个字节,并将新拼接的字符串提交加密,再记录返回结果,如果可以,那么再进一步解密出原文。
到这里,我们大概对此漏洞有了一个清晰的认识,欲深入分析请查看上面的PDF文档。
再回过来看ScottGu公布的解决方案,我的猜想是:
在错误页面中进行了随机的sleep,使得攻击者无法获取准确的返回状态,即无法获取应该返回的oracle。
添加错误配置节,当攻击者第一次尝试破解时,被配置节强制跳转到错误页面,在错误页面中,如果发现提交过来的构造密码种子(我理解成了种子 :) )为1,那么就将其对象强行Dispose掉,那么攻击者也就没法继续下去了。
在这一attack的原创者之一julianor的推特中说到:The attack that was shown in the public relies on a feature in ASP.NET that allows files (typically javascript and css) to be downloaded, and which is secured with a key that is sent as part of the request. Unfortunately if you are able to forge a key you can use this feature to download the web.config file of an application (but not files outside of the application). We will obviously release a patch for this - until then the above workaround closes the attack vector.
应该是针对WebResource.axd和ScriptResource.axd的。
Update[2010-09-21]:查看博友Sword-Breaker回复中的观点
小结
那么微软将如何去修复此漏洞呢,修改加密机制,还是......,持续关注。
好了,我的分析就到这里,也很晚了,文章中欠妥的地方,欢迎拍砖,一起再讨论下!