CBC加密原理及攻擊


原理
基於分組加密
加密過程


Plaintext:明文,待加密的數據。
IV:用於隨機化加密的比特塊,保證即使對相同明文多次加密,也可以得到不同的密文,初始向量,用來與第一塊的明文異或運算。
Key:被一些如AES的對稱加密算法使用。
Ciphertext:密文,加密后的數據。
在這里重要的一點是,CBC工作於一個固定長度的比特組,將其稱之為塊。在本文中,我們將使用包含16字節的塊。
• Ciphertext-0 = Encrypt(Plaintext XOR IV)—只用於第一個組塊
• Ciphertext-N= Encrypt(Plaintext XOR Ciphertext-N-1)—用於第二及剩下的組塊
XOR為異或運算 , N為第N塊數據
---------------------------------------------------------------------------
上述的公式和圖可以簡單描述為:
1.將要CBC加密的數據分為N個塊,每個塊為16字節
2.隨機找一個IV(初始向量),大小為每個塊的大小(16字節),用於與第一個塊進行異或運算
3.將異或運算的結果進行選定的加密方式進行加密
4.將得到的第一塊密文與第二塊明文進行異或運算
5.將異或運算的結果進行選定的加密方式進行加密
6.將得到的第二塊密文與第三塊明文進行異或運算
7.將異或運算的結果進行選定的加密方式進行加密
8.最后得到三塊加密獲得的密文
注意:正如你所見,前一塊的密文用來產生后一塊的密文。
----------------------------------------------------------------------
解密過程
Decryption Process

 

 

 
• Plaintext-0 = Decrypt(Ciphertext) XOR IV—只用於第一個組塊
• Plaintext-N= Decrypt(Ciphertext) XOR Ciphertext-N-1—用於第二及剩下的組塊
• -----------------------------------------------------------------------------------
上述的公式和圖可以簡單描述為:
1.將已經CBC加密的數據分為N個塊,每個塊為16字節
2.將第一塊加密的數據用選定的加密方式解密
3.找到加密時的IV,用於與第一個解密后的塊進行異或運算,得到第一塊的明文
4.將第二塊加密數據進行解密
5.用第一塊加密的密文與第二塊解密的塊進行異或運算,得到第二塊的明文
6.將第三塊加密的數據進行解密
7.用第二塊加密的數據與第三塊解密的塊進行異或運算,得到第二塊的明文
通過上述的解密過程可以推算出:
如果要修改第二個塊中的第n個字節的數據,只要修改第一塊數據的密文中的第n個字節數據,這樣第一個塊的密文與第二個塊解密得到的數據進行異或運算時就可以得到自己想要的數據,對第三個塊及其以后的數據都不會產生影響(因為與下一塊進行異或運算的都是加密的數據,第二塊的加密數據沒有進行改變),但是第一個塊修改了加密數據,進行解密和與IV異或運算后會產生錯誤數據。
以此類推,如果要修改第三塊中的數據,就修改第二塊的加密信息,會產生錯誤數據的只有第二塊數據,其他塊的數據不會產生錯誤。
如果要修改第一塊的數據的話,只能修改第一塊密文,這需要知道IV是什么,過程:
1.將第一塊的明文修改成想要的數據
2.將修改完的數據與IV進行異或運算,然后進行選定方式的加密,得到密文數據
3.將第一塊的密文數據換成的到的密文數據
這樣的話會出現錯誤的塊是第二塊,因為第一塊的密文修改了,與第二塊的已解密的數據進行異或運算時產生錯誤。
解決錯誤的方式是修改IV
-----------------------------------------------------------------------------
注意:Ciphertext-N-1(密文-N-1)是用來產生下一塊明文;這就是字節翻轉攻擊開始發揮作用的地方。如果我們改變Ciphertext-N-1(密文-N-1)的一個字節,然后與下一個解密后的組塊異或,我們就可以得到一個不同的明文了!You got it?別擔心,下面我們將看到一個詳細的例子。與此同時,下面的這張圖也可以很好地說明這種攻擊:

0x02 一個例子(CBC Blocks of 16 bytes)

比方說,我們有這樣的明文序列:
a:2:{s:4:"name";s:6:"sdsdsd";s:8:"greeting";s:20:"echo 'Hello sdsdsd!'";}
我們的目標是將“s:6”當中的數字6轉換成數字“7”。我們需要做的第一件事就是把明文分成16個字節的塊:
• Block 1:a:2:{s:4:"name";
• Block 2:s:6:"sdsdsd";s:8
• Block 3::"greeting";s:20
• Block 4::"echo 'Hello sd
• Block 5:sdsd!'";}
因此,我們的目標字符位於塊2,這意味着我們需要改變塊1的密文來改變第二塊的明文。
有一條經驗法則是(注:結合上面的說明圖可以得到),你在密文中改變的字節,只會影響到在下一明文當中,具有相同偏移量的字節。所以我們目標的偏移量是2:
• [0] = s
• [1]= :
• [2] =6
因此我們要改變在第一個密文塊當中,偏移量是2的字節。正如你在下面的代碼當中看到的,在第2行我們得到了整個數據的密文,然后在第3行中,我們改變塊1中偏移量為2的字節,最后我們再調用解密函數。
1. $v = "a:2:{s:4:"name";s:6:"sdsdsd";s:8:"greeting";s:20:"echo 'Hello sdsdsd!'";}";
2. $enc = @encrypt($v);
3. $enc[2] = chr(ord($enc[2]) ^ ord("6") ^ ord ("7"));
4. $b = @decrypt($enc);
運行這段代碼后,我們可以將數字6變為7:

但是我們在第3行中,是如何改變字節成為我們想要的值呢?
基於上述的解密過程,我們知道有,A = Decrypt(Ciphertext)與B = Ciphertext-N-1異或后最終得到C = 6。等價於:
C = A XOR B
所以,我們唯一不知道的值就是A(注:對於B,C來說)(block cipher decryption);借由XOR,我們可以很輕易地得到A的值:
A = B XOR C
最后,A XOR B XOR C等於0。有了這個公式,我們可以在XOR運算的末尾處設置我們自己的值,就像這樣:
A XOR B XOR C XOR "7"會在塊2的明文當中,偏移量為2的字節處得到7
--------------------------------------------------------------------
異或計算的公式:
1.A XOR B =C ,       B XOR C=A,       A XOR C =B
2.A XOR B XOR C =0

3.0 XOR A = A
----------------------------------------------------------------

Demo

目前自己測試只能修改第二塊和第一塊數據
源碼:
 function login($info){
      $iv = get_random_iv();
     $plain = serialize($info);
     $cipher = openssl_encrypt($plain, aes-128-cbc, SECRET_KEY, OPENSSL_RAW_DATA, $iv);
      $_SESSION['username'] = $info['username'];
      setcookie("iv", base64_encode($iv));
     setcookie("cipher", base64_encode($cipher));
 }
  function check_login(){
      if(isset($_COOKIE['cipher']) && isset($_COOKIE['iv'])){
          $cipher = base64_decode($_COOKIE['cipher']);
          $iv = base64_decode($_COOKIE["iv"]);
          if($plain = openssl_decrypt($cipher, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv)){
              $info = unserialize($plain) or die("<p>base64_decode('".base64_encode($plain)."') can't unserialize</p>");
              $_SESSION['username'] = $info['username'];
          }else{
              die("ERROR!");
          }
      }
  }
 if(isset($_POST['username']) && isset($_POST['password'])){
      $username = (string)$_POST['username'];
      $password = (string)$_POST['password'];
      if($username === 'admin'){
          exit('<p>admin are not allowed to login</p>');
      }else{
          $info = array('username'=>$username,'password'=>$password);
          login($info);
          show_homepage();
      }
  else{
      if(isset($_SESSION["username"])){
          check_login();
          show_homepage();
      }


輸入用戶名admir密碼1,抓取數據內容為:
Cookie:
PHPSESSID=iq1lrnq2fhp235ndd4ke2njl73;
iv=XyP2qyLI00SzmCP8t766mA%3d%3d;
cipher=8Rhxwqez6NPucPx4mKM4oytL0QCEM6YnRhjkPTjIVvDMp8HAF2%2f8JjiWG8oSLqwgdGs4EV018W7SU63K3bYV9w%3d%3d

過程: XOR異或 、CRYPT加密(未知密鑰)、en-加密后
plain XOR iv ->after_plain   CRYPT ->en-after_plain

補充:AES加密后的數據為16字節的整數倍,可直接進行異或運算

解題過程:
<?php
$enc=base64_decode("bIpgPK29vVQosJ+smzh0pOdq7QrP3H9CN0MBfynL1eKtILs/ayew1snTYbeYSIz8rQctkAUMORS76SWQHXwuKg==");
$enc[13] = chr(ord($enc[13]) ^ ord("k") ^ ord ("n"));
echo base64_encode($enc);
?>
 
<?php
$enc=base64_decode("4quudO++PAeVPQfcFJ0bbm1lIjtzOjU6ImFkbWluIjtzOjg6InBhc3N3b3JkIjtzOjM6IjEyMyI7fQ==");
$iv=base64_decode("TrphJjWLH37sj6+EBqh28A==");
$cleartext = 'a:2:{s:8:"userna';
$newiv = '';
for ($i=0;$i<16;$i++){
    $newiv=$newiv.chr(ord($iv[$i]) ^ ord($enc[$i]) ^ ord ($cleartext[$i]));
}
echo base64_encode($newiv);
?>
詳解:
    1. $enc = en-after_plain
    2. 因為序列化的內容為
    a:2:{s:8:"userna
    me";s:5:"admik";  
    s:8:"password";s
    :1:"1";}
    所以修改塊二上的第13位數據(從0開始),因此修改塊一13位數據(AES加密)
    3. 修改數據計算:

  

 

 
    1.算法
    ciphertext XOR plaintext  = 加密前xor后的plain
    加密前xor后的plain XOR plaintext =ciphertext
    所以比如要修改enc[23]處的值時,使用的算法為enc[7]^"替換前"^"替換后"
注意錯誤:不能使用加密后直接異或,從過程來看就為錯誤
          例如enc[23]^"H"就是錯誤的,因為加密后原本異或后位置的字符改變
    2.關於改變后iv的獲得
    由於數據改變導致第一塊數據異或時得到不能序列化的數據,所以需要根據網頁返回的不能序列化的數據(也就是除iv修改完后塊一的數據,base64解碼后就是序列化數據)進行異或運算來的得到新的iv
    與前面的1 運算相同
    iv XOR 網頁返回的數據 = 加密前xor后的plain(序列化錯誤的)
    加密前xor后的plain XOR plain(正常序列的) = new_iv
    所以得到iv算法為  iv ^ wrong_plain ^ plain
    補充:由於加密解密得關系 所以不只是特定位置的字符錯誤,需要全部異或計算

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM