Padding-Oracle-Attack详解

Padding-Oracle-Attack详解


2024年4月26日发(作者:三星s7562手机)

Padding Oracle Attack详解

关于Padding Oracle Attack,最好的文章也许要算

/l/b/2010/09/14/automated-padding-oracle-attacks-wit

h-padbuster/了。我只是以这篇文章为基础写一版中文的介绍文章,并加上我自

己的一些想法重新组织资料调整结构,希望能够降低门槛让更多的人看懂。由于

涉及到一些加密的概念,而加密我并没有深入了解过,所以这里只写出需要用到

那一小部分,估计还是难免会有一些错误,。

只知道攻击而不知道原理无疑是可悲的。

云舒(wustyunshu@)

2010年9月28日,Ph4nt0m、80sec

一、 背景知识

1.1 分组密码和填充

常用的对称加密算法,如3DES、AES在加密时一般使用分组密码(Block Cipher)。

将明文以数据块(Block)为单位进行加密,常见的如64 bit、128 bit、256 bit,

而不是每次只加密一个比特。

这样就带来一个问题,数据的长度不可能恰好是block的整数倍。较长的数据就

涉及到分组操作,不能整除的剩余部分数据就涉及到填充操作。分组比较简单直

接按照bit切分即可,填充方法最常见的是PKCS#5,在最后一个block中将不足

的bit位数以bit为值填充。最后一个block缺少5 bit,则填充5个0x05到block

结尾,缺少2 bit则填充2个0x02到结尾。以64 bit的block举例:

1.2 分组密码加密的模式

上一节描述了如何将明文按照指定大小的block进行分组,如何将位数不足的

block填充补足,现在就可以开始加密了。分组密码加密有四种模式,分别是ECB、

CBC、CFB和OFB,其中CBC是IPSEC的标准做法,这里主要介绍。

CBC(Cipher Block Chaining)引入了一个随机的初始化向量( initialization vector)

来加强密文的随机性,保证相同的明文多次加密都得到不一样的密文。明文先与

初始化向量做XOR操作,然后按照加密算法加密。同时,上一个block加密后的

密文作为下一个block的初始化向量,用来保证更强的安全性。需要注意的是,

这个初始化向量会带在密文当中,否则解密端不知道初始化向量也无法解密密文。

加密过程如下图:

二、 Padding Oracle Attack

2.1 问题的原因

明文分组和填充就是Padding Oracle Attack的根源所在,但是这些需要一个前提,

那就是应用程序对异常的处理。当提交的加密后的数据中出现错误的填充信息时,

不够健壮的应用程序解密时报错,直接抛出“填充错误”异常信息。

攻击者就是利用这个异常来做一些事情,假设有这样一个场景,一个WEB程序

接受一个加密后的字符串作为参数,这个参数包含用户名、公司ID和角色ID。

参数加密使用的最安全的CBC模式,每一个block有一个初始化向量。当提交参

数时,服务端的返回结果会有下面3种情况:

a. 参数是一串正确的密文,分组、填充、加密都是对的,包含的内容也是正确

的,那么服务端解密、检测用户权限都没有问题,返回HTTP 200。

b. 参数是一串错误的密文,包含不正确的bit填充,那么服务端解密时就会抛出

异常,返回HTTP 500 server error。

c. 参数是一串正确的密文,包含的用户名是错误的,那么服务端解密之后检测

权限不通过,但是依旧会返回HTTP 200或者HTTP 302,而不是HTTP 500。

攻击者无需关心用户名是否正确,只需要提交错误的密文,根据HTTP Code即可

做出攻击。根据应用程序的状态码在不知道密钥的情况下一个bit一个bit的猜

解出密文对应的明文,也可以伪造出任意明文加密后的密文。

2.2 根据密文猜解明文

假设有这样一个应用,

sampleapp/?UID=7B216A634951170FF851D6CC68FC9537858795A2

8ED4AAC6,我们来看看在不知道明文的情况下,如何破解出明文。首先将密文

分组,前面8字节是初始化向量,后面的16字节就是加密后的数据,如下图(为

了更清晰的说明加密解密的变化过程,这里把明文标出了):

根据上面分组密码加密模式中的加密图示,我们先看看BARIN;12;1是如何被加

密的。

类似的,解密只不过是一个逆向的过程,如下图:

现在开始破解了,我们先将初始化向量设置为0,提交如下请求,

sampleapp/?UID=0000F851D6CC68FC9537,服务器

势必返回一个HTTP 500的服务器错误信息,因为对第一个block解密的时候XOR

初始化向量得到最后一个字节是0x3D,这显然是一个错误的填充。这时候解密

示意图如下:

现在我们在初始化向量全0的情况下变化最后一个字节为0x01,提交请求

sampleapp/?UID=0001F851D6CC68FC9537,如上次

请求一样服务器继续返回一个HTTP 500的服务器错误信息,解密示意图如下:

我们将最后一个字节从0x00逐渐往0xFF方向递增,迟早会猜测到一个正确的值,

让填充的最后一个字节是0x01,成为一个正确的padding。当初始化向量是

003C的时候,成功了,服务器返回HTTP 200,解密示意图如下:

根据XOR的交换性可以知道解密时一个临时中间值(Intermediary Value)最后一

个字节是0x3D,因此可以预测当初始化向量最后一个字节是0x3F的时候,

padding的最后一个字节会是0x02。现在将初始化向量的最后一个字节设置为

0x3F,变化其倒数第二个字节,开始猜解临时中间值的倒数第二个字节。猜解成

功时示意图如下:

以此类推,我们可以猜解出完整的临时中间值。

同样基于XOR的交换性,我们将临时中间值(0x39 0x73 0x23 0x22 0x07 0x6A 0x26

0x3D)与我们要猜解的被加密的串(7B216A634951170F)做XOR即可得到明文

的第一个block即BRIAN;12

同样的方式,即可猜解密文的第二个block的明文。需要注意的是,第一个block

的密文F851D6CC68FC9537将是第二个密文的初始化向量。推而广之,前一个

block的密文是后一个block的初始化向量。

2.3 伪造指定内容的密文

伪造指定内容的密文,才是真正攻击的开始。我们可以伪造cookie,伪造WAP

站点的SID等等内容。在上一节中,我们知道密文F851D6CC68FC9537经过解密

(3DES还是AES?密钥是多少?你还问这个,我们需要这个么?)后的临时中间

值是39732322076A263D,那么我们只需要传递指定的初始化向量,就能XOR出

我们想要的任何值。比如说加密TEST,示意图如下:

也就是说,我们只需要将6D367076036E2239作为密文的初始化向量,

F851D6CC68FC9537作为密文提交上去,服务端解密后必然解密出TEST,后面加

4字节的填充。

如果更长的密文该怎么伪造了?因为初始化向量每个block都不同,而且前一个

block会影响后一个block,因此我们需要先将明文分组,从最后一个block算起。

至于具体的计算,就不说了,稍微想想就能明白。

2.4 .NET框架的问题

这个漏洞在/a/20100926/有详细的描述,只是作者

精通.NET开发而不懂安全,所以没有办法描述为什么会这样。说到底,下载

不过就是一个伪造制定内容的密文的问题。

这是一种攻击思路,而不应该局限为一种手段,应该有很多应用会被类似的攻击

所威胁。


发布者:admin,转转请注明出处:http://www.yc00.com/num/1714099752a2381125.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信