本文目的
向非安全方向的技术人员,特别是软件架构师介绍Padding Oracle的基本原理及其危害,以避免无意中在软件设计和技术选型过程里留下安全隐患。
Padding Oracle Attack的一些背景资料
这个攻击引起广泛关注是在今年5月的ekoparty安全会议上,两位安全工程师Julinao Rizzo和Thai Duong共同发表了一篇名为Practical Padding Oracle Attacks的论文。由于考虑到这个漏洞的广泛性及攻击可能带来的严重后果,他们的论文中并没有对原理做过多详述。只是从理论上描述了这个概念,并在大会上做了一些演示。
此后在安全界,很多高手纷纷独立做出了自己的PoS,网上目前可以搜到的资料中,以演示攻击的视频为主。同时还陆续有一些检测(而不是攻击)工具发布。这些Hacker们严格遵循着自己的道德准则,在业界没有做出反应之前,并没有让这一技术迅速扩散到脚本小子的手中。
目前国外详细介绍文章不多,可看的主要有以下这些:
- PPOA
- Automated Padding Oracle Attacks with PadBuster
- Padding Oracle Attacks on CBC-mode Encryption with Secret and Random IVs
- Understanding Padding Oracle attacks
国内唯二的两篇有价值的文章是来自于盛大创新院的赵喆:
如果你对这个攻击的技术原理特别感兴趣,推荐你在阅读完本文后继续阅读以上文章。即使是这些文章,作者可能出于一些考量,其中的某些描述存在故意误导的成分,请带着思考阅读。网上目前公开的所有其它关于Padding Oracle Attack的文章以胡说和凑热闹的居多,没有干货。甚至有一些给出的建议完全驴头不对马嘴,遗毒匪浅。
Padding Oracle Attack的基本原理
一点预备知识:
1. 在对称加密算法中,得到密文的基本原理是,密文=加密算法(明文,密钥)。
2. DES, RC2等加密算法里面的加密是分块实施的。每块固定n(8, 16, 32…)位,有余数的情况一般按照指定规则补足,称之为Padding.
3. 为保证加密算法的复杂度,上一块的密文会被用于混淆下一块加密数据。以此类推。用来混淆第一块数据的是预先生成的IV(初始化向量)。
4. 为保证针对同一明文和密钥的密文每次都不一样,Web应用中通常会随机生成IV,并将它附加在密文中进行传输。
5. 解密时,解密算法回收密文中携带的IV,将密文逆向解密,拿到一个中间密文,然后使用IV逆向混淆此中间密文,随后检查Padding合法性,最后返回明文。
在完全理解以上5点的基础上,我们可以简单介绍一下Padding Oracle的基本原理了。
实际应用中,一个密文被解密时,也是分段进行的。解密完成之后算法会首先检查Padding是否符合规则,不符合的话,绝大多数算法实现都会抛出一个Padding Error异常。这个异常的抛出,被称之为Oracle:神谕。
攻击者在手中只有一个合法密文的情况下,通过不断向加密者发送篡改过的密文(这个过程主要是构造IV的过程),观察是否有Padding Error抛出,从而最终获得混淆之前的中间密文。拿到中间密文之后,可以通过构造IV,使得中间密文被逆向混淆之后得到的明文为指定内容,从而达到攻击的目的。
在这个过程中,混淆一般都非常简单而且是公开的。以DES为例,就是一个简单的异或。
从效率上,以一个8byte的IV构造为例,每个Byte最坏的情况需要尝试256次,总共是2048次。假设每次尝试的时间为5秒(HTTP响应时间),总共耗时在3个小时以内。此外本地的一些计算由于非常简单,所以一次成功的攻击所需要的平均耗时不会超过3个小时。
换句话说,Padding Oracle攻击并没有破解掉加密算法的密钥,也没有能力对任意密文做逆向解密,只是可以利用一个有效密文,生成一个解密后得到任意指定内容明文的伪造密文。
网上很多人声称对称加密算法不可靠了,DES被攻破了等等说法,都是不正确的。加密算法的有效性是经过数学证明的,算法的各平台实现也经过了时间检验,不会有问题。只有密文,在不知道密钥的情况下,依然是没有办法在可接受的时间内破解出明文。Padding Oracle攻击是针对对加密算法的一些滥用(Abuse)。
Padding Oracle Attack的攻击场景
在Web应用层,Padding Oracle Attack往往用于攻击一些依赖于对称加密算法做状态保持或者身份认证的场合。
想象一个业务场景:一个Web用户登录成功之后,服务器为了保持其状态,以及相应的身份、权限、用户组等信息,需要把用户的身份通过某种方式实现状态保持。由于使用Session对服务器的性能损耗较大,普遍的做法是存储一个加密过的身份ID,存储在Cookie或者URL Query String中,用以保持状态。在每次接收请求时,解密出身份ID,然后在本地缓存中取出该ID对应的相关权限信息。
在这个过程中,由于加密算法的密钥是对客户端保密的,因此普通认为这种做法比较安全。但是利用Padding Oracle攻击时,可以利用一个合法的密文,通过构造IV使得服务器解密过程合法,而解密后得到的身份ID已被篡改,从而达到Broken Access Control的效果。
利用这一攻击方式,可以有很多针对特定应用的攻击手段。ASP.NET 2.0提供的Web Resources管理模型中,利用WebResources.axd?d=41VAQHZc9t11gcfcSh8IynBrLxqhiiUYVpPeaSf8这样的URL从服务端获取资源文件,但是通过Padding Oracle,可以构造一段密文,被解密后等同于请求WebResources.axd?d=~/web.config。后果可想而知。
由于这一PoS简单命了,在网上被多次提及和演示。被夸大到似乎这是一个Asp.Net特有的安全问题,但是事实上只要通过对称加密算法的密文穿越安全边界(Security Boundary),都存在可被Padding Oracle攻击的漏洞。所以这是一个普遍存在的安全漏洞,Asp.Net只是受害者之一。
利用这一攻击手段,攻击者甚至可以构造出一段密文,完成XSS乃至Sql Injection攻击。
检测,防范和解决方案
首先,必须再次强调安全开发规范中的黄金法则:在每一次发生穿越安全边界的数据传输时,必须做安全校验。
针对Web应用,这意味着,你不能信任任何从Form, Query String, View State, Cookie, HTTP Header过来的任何数据。即使数据已经被你的私密密钥加密。
这种安全校验包括检查数据是否合法,是否有XSS或者Injection的可能,是否冒充等等。
针对身份冒充这一应用场景,解决方法可以是,在本地加密Cookie中,除了保存身份ID或者用户名等易猜测信息之外,还需要有一段数据用于存储针对此用户的保密信息,例如密码的散列。在服务端解密完成后进行校验。这样攻击者由于无法获知这段保密数据,也就无法完成BAC攻击。
总之,这是一个设计问题。
一个误区
论坛上看到有人谈Padding Oracle色变,弃用公开的加密算法,改由程序员自行开发加密算法(Home Grown Ones),这是错误的。
永远不要自行开发加密算法,是强调过很多次的安全编码原则之一,原因就不仔细解释了。
总结
作为2010年的最后一篇技术文章,我希望尽我所能把Padding Oracle Attack的简单攻击思路介绍清楚。但是由于不可避免涉及到一些密码学的基本原理,所以文章可读性依然不如人意,感谢您还能读到这里。
2010年的安全圈发生了很多有意思的事情,今年的Red Hat大会上甚至有Hacker当众演示了如何利用一个1500美元的小型工作站劫持GSM基站并且戏弄了几名参会者(当然这个演示事先得到了FCC的批准从而不会产生法律问题),但这也只是利用了简单的BAC漏洞而已。从攻击原理上来说,我认为Padding Oracle是2010年度最具技术含量的攻击手法。
期待2011年是更具惊喜的一年。作为一个专注于应用安全的技术人员,我也会向开发者社区介绍更多的安全界动态。
本文转载自:http://www.unclejoey.com/?p=454