14

SSL/TLS协议安全系列:CBC 模式的弱安全性介绍(一) | WooYun知识库

 7 years ago
source link:
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

SSL/TLS协议安全系列:CBC 模式的弱安全性介绍(一)

编辑标注: 因drops对数学符号的支持存在问题,所以部分内容采取图片的形式显示,我们会经快解决这个问题,希望见谅。

一 前言


在SSL的一些版本中,使用CBC分组模式对数据进行加密,而CBC分组模式在使用中常会出现一些问题。本文对CBC分组模式中Padding Oracle Attack做基本介绍,主要包括Padding Oracle Attack的背景知识、在多种填充模式下的攻击原理以及现实场景应用。

Padding Oracle Attack,顾名思义:Padding是“填充”,这里指在CBC分组加密模式中的填充数据;Oracle是“提示”,意指服务器返回的提示信息。Padding Oracle Attack可理解为“填充提示攻击”,是一种逻辑上的旁路攻击。简要来说,Padding Oracle Attack是指以明文分组和填充为根源,依据系统解密密文时泄露的填充信息,通过不断尝试填充字节直到获得有效填充信息,从而恢复出明文或者构造任意明文对应的密文这样一种攻击方式。利用Padding Oracle Attack,恢复一块长度为b字节的密文块,只需要平均128*b次oracle回应,而不是尝试2^k次(k指密钥长度为多少bit)。

Padding Oracle Attack最初是Serge Vaudenay在EUROCRYPT 2002会议上提出, Vaudenay介绍了CBC模式中基本的Padding Oracle Attack攻击原理;在 2010 年的 BlackHat 欧洲大会上,Juliano Rizzo 与 Thai Duong 把这种攻击应用到了一些流行的Web应用框架上,包括JavaServer Faces,Ruby on Rails 以及 ASP.NET,他们在2011年的Symposium on Security and Privacy大会上发表文章详细分析ASP.NET中的Padding Oracle问题;同年,在Pwnie Rewards中,ASP.NET的Padding Oracle漏洞被评为“最具价值的服务器漏洞”;次年,Romain Bardou和Riccardo Focardi等人发现,这种攻击对于一些安全设备同样有效;在 2014年,谷歌的安全人员又提出了针对 SSL v3协议中Padding Oracle漏洞的POODLE攻击,99%以上使用 https 服务的网站受到影响。

二 背景知识


在介绍Padding Oracle Attack原理之前,这里首先简单介绍一些相关的背景知识。

CBC(Cipher Block Chaining)分组模式

常用的对称加密算法(如AES、3DES等),一般使用分组加密模式,其中CBC是最常见的分组模式之一。CBC分组模式在对消息进行加/解密时,会根据使用的不同对称加密算法,将消息进行分块(block),每块大小可被分为16字节(AES)、8字节(3DES等)。

CBC分组模式加密流程如下图:

enter image description here

CBC分组模式中引入初始化随机向量IV,使得相同明文在不同的加密次数中产生不同的密文,IV随密文一起发送给接收方。整个加密过程可以表示为:

enter image description here

其中C表示密文块,P表示明文块。从加密过程中,我们可以看出,每一块明文都需要是整齐的,由于在现实中明文不一定可以整齐的分成块,因此在最后一块明文中需要加入填充(Padding)。

CBC分组模式解密流程图:

enter image description here

首先每块密文经过对称算法解密成中间值,之后同前一块密文异或得到明文。解密过程可以表示为:enter image description here 根据CBC分组模式加/解密过程可以看出,假如改变C_i的任何一位,解密时会影响到P_i和P_(i+1),同时,如果有一块密文改变,也只会影响到它对应的以及之后的一块明文的内容。

几种填充方式

前面我们提到,明文信息可以是任意长度,不一定是block的整数倍,这样难免明文分组后最后一块长度不足。解决的方法就是对最后一块内容进行填充,这里我们介绍几种常见的填充规范。

  1. PKCS#5

最常见填充规范是PKCS#5,PKCS#5标准的全称是“Public-Key Cryptography Standards”,在 RFC2898里有说明。简单的说,如果最后一块明文缺少N个字节,就用N这个数填充到完整的块。我们以8字节为一块的分组模式举例:

enter image description here

  1. ISO/IEC 9797-1

PKCS#5只是常用的填充标准之一,ISO/IEC也提供了两种填充的标准,分别为ISO/IEC 9797-1和ISO/IEC 10118-1,这里我们具体介绍前一种填充标准,并在后面给出对应的Padding Oracle Attack方法。

ISO/IEC 9797-1标准有三种填充方式:

第一种在明文后面全部补‘0’,直到是block size的整数倍;

第二种在明文后面紧跟着的一位补‘1’,之后补‘0’,直到是block size的整数倍;

第三种方式:

enter image description here

假设分组模式每块长度为n(bit),首先右填充,在明文后面全部补充‘0’,直到n的整数倍,然后再进行左填充,(L_D)_2是未填充的明文长度(用bit表示)的二进制表示,然后在该长度左边补充‘0’直到长度为n。这种填充方式如果数据为空,仍然会有一个全‘0’的块作为填充。针对第三种填充方法,我们后面会给出对应的攻击原理。

上面介绍的两种标准,第一种是按字节填充,第二种是按位填充。除了这两种标准,还有很多其他的填充方式,比如John Black和Hector Urtubia在USENIX 2002年大会上提出的,这里我们以4字节填充为例介绍:

enter image description here

XY-PAD:选取固定的X和Y,在明文最后填充一个X,之后填充足够的Y;

ESP-PAD:在明文最后填充123..n补齐;

PAIR-PAD:与XY-PAD类似,这里的X和Y不是固定值,每次随机选取;

OZ-PAD:按位填充,在明文最后填充‘1’bit,之后以‘0’补齐;

ABIT-PAD:按位填充,发送者检测明文最后一位是‘0’还是‘1’,在最后以相反的位进行填充;

ABYT-PAD:发送者检测明文最后一个字节,然后选取任意不同的字节‘Y’进行填充;

BOZ-PAD:同XY-PAD,只不过X取的是0x80,Y取0x00。

三 攻击原理


1 攻击实施条件:

Padding Oracle Attack依赖于两个假设,也就是实施攻击需要满足的先决条件:

  • 攻击者可以窃听通信,并且拦截CBC分组模式的密文。
  • 攻击者能够访问一个padding oracle O,并且能够区分返回的响应信息表示填充‘有效’或者‘无效’。

另一点是基于服务器的响应,服务器解密和验证padding时返回的不同信息:

  • 当信息解密和填充都合法时,服务器会返回类似200 OK这样的有效信息;
  • 如果解密过程中填充正确,但是消息内容不正确,也会返回200 OK;
  • 如果出现填充错误,我们就会得到一个密码学异常和一个类似 500 Internal Server Error的响应。比如JSF view states填充错误时,会返回 javax.crypto.BadPaddingException: Given final block not properly padded。这就很明显的告诉我们此时填充不正确。

由此可见,攻击者能够很容易的根据错误消息判断填充是否有效,相当于能够访问一个padding oracle。

2、如何解密

(1)PKCS#5

这里我们首先以PKCS#5填充标准为例,介绍Serge Vaudenay在EURO-CRYPT 2002上提出的Padding Oracle Attack的基本原理。

首先给出几个符号定义,‘b’表示block的字节长度,比如AES中b=16,DES中b=8;N表示明文包含的block数量;在PKCS#5中,一个block序列x1, x2,……xN填充有效,是指xN最后一个字节为0x01,或者最后两个字节为0x02,0x02,以此类推。

<1 Last Word Oracle:

Last Word Oracle,能够获得任意密文块y最后一个字节对应的明文内容。如图所示:

enter image description here

enter image description here

当然也会出现填充为0x02,0x02或者0x03,0x03,0x03这样的情况,这时也会返回valid,此时从r的最左端一个字节更改,观察是否返回仍然为valid,如果是说明从这个字节往后都是填充,否则向右移动更改r的字节。Vaudenay给出了具体的实施过程:

enter image description here

这个过程的思想就是枚举‘IV’,密文y解密的中间值不变,通过枚举r,使得异或后的明文产生变化,根据填充方式的特征以及返回的Oracle信息,判断异或后明文最后字节的内容,从而获得中间值对应字节的内容,进一步与前一密文块对应字节异或得到y的最终明文。

<2 Block Decryption Oracle

获得密文块y最后一个字节明文内容后,可以通过修改r_b的值,使得C^(-1) (y)⊕r最后一个字节值为0x02,然后枚举r_(b-1),如果得到O(r||y)=valid,说明倒数第二字节内容也为0x02,进一步得到倒数第二字节的内容,依此恢复出整个block的内容。

enter image description here

以上Padding Oracle Attack攻击原理,是Vaudenay于EUROCRYPT 2002大会上提出,主要针对PKCS#5填充标准。下面介绍对于其他填充方式的Padding Oracle Attack。

(2) ISO/IEC 9797-1

ISO/IEC 9797-1第三种填充方式上面我们介绍过:

enter image description here

针对ISO/IEC 9797-1第三种填充方式的Padding Oracle Attack,是Kenneth G. Paterson等在2004年CT-RSA大会上提出,攻击方式分为两个步骤:

<1 确定L_D

enter image description here

第一种情况:填充完之后数据block数量q>=3(包括L_D)

在CBC分组模式中,改变密文块C_j中第i位,同时会影响解密后的明文P_(j+1)的第i位。当更改倒数第二块密文块C_(q-1)的任意一位,最后一块明文P_q对应的位也会改变。因为q>=3,所以倒数第二块不会是L_D对应的密文,L_D内容不会被修改。将更改后的密文发送给Oracle会有两种情况发生:

  • 更改到的位是原始的非填充内容。填充信息仍然是完整正确的,这时Oracle会返回valid。
  • 更改的位置是padding内容。这时根据L_D计算的填充信息会错误,Oracle返回invalid。

对于返回valid的情况,将更改位向右移动继续尝试,invalid情况,更改位向左移动,直到移动到填充有效和无效的边界,这时就可以得知填充的位数,从而计算出L_D的内容。

第二种情况:填充之后数据block数量q=2

enter image description here

第三种情况:q=2, L_D=0或者L_D=n

构造enter image description here

当L_D=0时,未填充明文数据长度为3n,Oracle会返回invalid;L_D=n时,未填充明文数据长度为2n,Oracle会返回valid。从这种方法判断L_D内容。 <2>解密数据

enter image description here

enter image description here

enter image description here

以上就是ISO/IEC9797-1标准第三种填充方式的解密原理。

John Black和Hector Urtubia提出的一些填充方式,可以使用类似PKCS#5的攻击方式进行解密,这里不再详细描述。

3、CBC-R

CBC-R是由John Black和Hector Urtubia 在Blackhat Europe 2010大会上提出,攻击者可以在不知道密钥K的情况下,构造任意明文对应的密文。

回顾一下CBC解密公式:enter image description here

如果攻击者获得了C_(i-1)和D_k (C_i),他就可以控制明文P_i的内容。由于攻击者目的是获得任意明文P_i对应的密文C_i,那么对C_(i-1)可以做任意更改。攻击过程如下:

  • 攻击者从截获的数据中任意选择C_i;
  • 根据前面介绍的Block Decryption Oracle方法,获得D_k (C_i );
  • 异或D_k (C_i )和P_i就可以获得C_(i-1)的内容。

用这种方法,会使P_(i-1)的内容混乱,但是依此修改C_(i-2)的值可以构造P_(i-2),依此类推构造整个密文块。具体算法如下:

enter image description here

在CBC-R攻击中,会出现IV问题。攻击者在构造任意明文对应的密文时,依此类推最后需要修改C_0也就是IV的值,而在现实应用中,IV可能并不能被攻击者控制。IV在现实应用中可能有以下几种情况:

  • IV是密文的一部分,可以完全被攻击者控制;
  • IV是固定且公开的值,不能被攻击者修改;
  • IV保密且固定;
  • IV保密且会变化。

对于IV不受攻击者控制的情况,也有解决办法。

假如服务器希望收到头部(第一块明文)含有某些特定信息的数据,并且此时IV不能被控制,这时候可以牺牲中间某块数据的含义,获得有效的头部数据:

enter image description here

C_capture是攻击者截获的头部密文,这样解密后只是中间某个block失去意义。

四 现实应用


1. POODLE攻击

CVE-2014-3566描述了POODLE(Padding Oracle On Downgraded Legacy Encryption)攻击。在SSL v3.0版本中,CBC分组模式填充方式为:·······N,最后一个字节表示填充内容的长度。这种攻击利用SSL v3.0版本对数据先认证后加密的漏洞,使得攻击者可以拿到服务器返回的填充有效(无效)信息,同时攻击者可以截获修改密文,满足实施Padding Oracle Attack的先决条件,从而利用Padding Oracle Attack获取明文内容。攻击者通过控制HTTP请求的路径和主体,使需要解密的敏感信息与分组块对齐,并将对应的密文块放在密文最后,通过多次发送该请求,获得该密文块最后一个字节内容,然后修改HTTP请求的路径,移动敏感数据下一个字节到密文块边缘。依此类推获得敏感信息。

2. Lucky 13

CVE-2013-0169描述了Lucky 13攻击。简单来说,该攻击利用服务器验证HMAC产生的时间差异,进行明文恢复。当服务器检测完CBC分组模式padding时,并不马上返回Oracle,此时会计算HMAC是否正确。而在计算HMAC时,会因为明文长度不同,计算时间也不同。攻击者通过修改密文,利用HMAC计算时间不同,猜测修改后的密文对应的明文的padding内容,依此获得明文信息。

对于Padding Oracle Attack的应用场景还有很多,比如ASP.NET,JSF view states等,这些很多资料中讨论较多,这里不再详细说明。

五 防范方法


Padding Oracle Attack的实施条件中提到,攻击者需要截获修改密文内容,另外能够从服务器获取Oracle信息。在使用CBC分组模式时,如果先进行数据填充和加密,然后进行MAC完整性验证,解密之前先检测MAC,再检查padding,就不会出现padding oracle,这样就阻止了攻击者进行此类攻击。

在TLS1.2版本中,使用的是AEAD (Authenticated Encryption with Additional Data),也就是AES-GCM模式,避免了使用CBC分组模式,同时避免了类似Padding Oracle Attack攻击。


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK