SSL/TLS協議安全系列:CBC 模式的弱安全性介紹(一)

wyzsk發表於2020-08-19
作者: GoSSIP_SJTU · 2015/06/24 10:45

編輯標註: 因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攻擊。

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章