Padding Oracle Attack學習筆記

Padding Oracle Attack學習筆記

前言

最近看到Padding Oracle Attack,是對加密算法的CBC模式的破解,很是好奇,找了些資料,動手實現了破解算法。 但是過程有點點曲折,記錄下心得體會。

原理

以DES的CBC模式爲例,分組加密算法在加解密時,都需要把消息分組,一般爲8或16字節。以解密爲例:
分組解密

理解破解算法的幾個關鍵點:

關鍵點1:padding bytes

padding bytes,即明文不足分組長度時,進行填充的字節。以8字節分組,PKCS5模式爲例,當明文爲HELLO時,不滿8個字節,剩餘3個字節的填充字節爲0x03,即:

padding byte = padding length = block size - block input length
//填充字節 等於 填充長度 等於 分組長度 - 分組輸入長度

因此,填充字節只能是0x01, 0x02…0x08。 0x08表示輸入長度爲8的倍數字節時,後面也會有8個字節的填充數組。 也就是說,填充字節肯定存在,且範圍是1~8。
(其他分組長度類似原理)

關鍵點2:padding error

當構造的輸入錯誤時,會產生padding error,如java中是BadPaddingException,其他語言可自行嘗試。 這點很關鍵,因爲Padding Oracle Attack的核心就是這個,利用padding error來不斷進行輸入嘗試。 編寫破解工具時,可能看不到異常,但是一定要能根據返回信息判斷是不是產生了padding error,如果不能確定,破解是進行不下去的。

關鍵點3:算法

與解密示意圖對應,我們將分組密文進行 block ciper decryption後得到的字節數組稱爲Intermdiate bytes,將與Intermediate bytes進行XOR的字節數組稱爲IV,分組密文用block表示,block[i]表示第i個分組密文, plain block[i]表示第i個分組明文,intermediate[i]表示第i個分組密文的Intermdiate bytes。

ok,讓我們捋一捋流程:

  1. block[i] decrypt得到 Intermediate bytes, 這個操作跟key(密鑰)有關,每個密文分組得到的Intermediate bytes是固定的

  2. Intetermedaite bytes 異或 IV 得到明文。注意圖中的解密過程,前面分組的密文會與後面一個分組的解密密文異或,最終得到後面一個分組的明文。即對應的block[i]的IV爲block[i-1]。因此,解密一定從最後一個分組開始。

  3. 從最後一個分組開始,用全0數組pseudo block[i-1]代替真實的block[i-1], 通過不斷的調整psdudo block[i-][7](最後一個字節),通過判斷是否返回padding error來確定填充字節是否正確,即0x01,如果正確,則意味着可以得到明文:

     if intermediate[i][7] XOR pseudo block[i-1][7] == 0x01:
     	//得到intermedaite bytes
     	intermediate[i][7] = pseudo block[i-1][7] XOR 0x01
     	//從而得到分組明文
     	plain block[i][7] = intermediate[i][7] XOR block[i-1][7]
    

    因爲一個字節的範圍是從0~255,所以對於一個字節的嘗試最多是256次,

  4. 如果構造數組得到正確的填充字節0x01,則意味着intermediate[i]的最後一個字節確定了,從而可以繼續調整,當填充字節爲0x02時:

     pseudo block[i-1][7] = intermediate[i][7] XOR 0x02
    

    調整pseudo block[i-1][6]的字節值,可以得到block[i][6]的明文字節;以此類推,block[i]就可以全部解密。

  5. 重複步驟3、4,即可以得到全部分組的明文。

遇到的坑

看完上面的原理,像我這種弱雞會覺得,“靠,這麼簡單,我要試一試”。 事實會再次證明你too young。。。

坑1

算法的第3點,爲毛要用全0數組充當僞造的數組,而且要從最後一個字節開始嘗試,且得到的填充字節就一定是0x01?

抱歉,我也沒有確定的答案,我找到的源碼和資料都是直接這麼搞的,更狠的是原作者的PPT上說的是random bytes(希望是我英語不好,讀的不仔細吧)。 但是我有個推測:block[i]密文decrypt操作得到的intermediate[i],字節重複且在0~8之前的概率非常之小。

因此,當從全0數組的最後一個字節開始嘗試時,遇到非padding error的情況,就極大概率對應填充字節爲0x01。 因爲,假設此時正確填充字節爲0x03,則意味着block[i]的5、6、7這3個字節對應的intermediate都是0x03。

當然,我覺得就算出現此類極端情況,也是有補救措施的。 比如對於填充字節0x01得出一個錯誤的pseudo block[i][7],那很可能對於0x02,得不出正確的pseudo block[i][6],這個時候退回去,跳過當前的pseudo block[i][7]值往後嘗試;以此類推,也可以推導出正確的結果。

當然這個是推測,需要翻算法和源碼驗證。

坑2

算法第5點,看似正確,轉念一想,對於第一個密文分組,咱是不知道原始IV的啊,怎麼破?

抱歉,這個真的無解。。。翻的資料都說“初始IV不重要,一般放在第一個分組,明文傳輸”。。。

剛開始看算法的時候,糾結了很久,因爲推不出第一個分組的明文,才一直覺得自己是沒有透徹理解原理,就是因爲沒有注意到這句話。。。

總結

看安全的材料,感覺搞安全的同學們還是挺NB的,佩服。。。不過,慣例,槽還是要吐的,上面那兩個坑,尤其第一個,搜到的材料都沒有解釋,看來大家都比較忙。。。

附錄:

  1. 《白帽子講WEB安全》
  2. 破解算法PPT
  3. PadBauster源碼地址
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章