原理
基于分组加密
加密过程

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
    补充:由于加密解密得关系 所以不只是特定位置的字符错误,需要全部异或计算

CBC加密原理及攻击的更多相关文章

  1. 分组密码CBC加密缺陷

    title: 分组密码CBC加密缺陷 date: 2017-05-15 10:04:47 tags: ["密码学"] --- 关于密码学的种种漏洞以及利用网上也有不少,但是比较零散 ...

  2. Atitit RSA非对称加密原理与解决方案

    Atitit RSA非对称加密原理与解决方案 1.1. 一.一点历史 1 1.2. 八.加密和解密 2 1.3. 二.基于RSA的消息传递机制  3 1.4. 基于rsa的授权验证机器码 4 1.5. ...

  3. Java实现SSH模式加密原理及代码

    一.SSH加密原理 SSH是先通过非对称加密告诉服务端一个对称加密口令,然后进行验证用户名和密码的时候,使用双方已经知道的加密口令进行加密和解密,见下图: 解释:SSH中为什么要使用非对称加密,又使用 ...

  4. HTTPS加密原理与过程

    HTTPS加密原理与过程 HTTP 超文本传输协议一种属于应用层的协议 缺点: 通信使用明文(不加密),内容可能会被窃听 不验证通信方的身份,因此有可能遭遇伪装 无法证明报文的完整性,所以有可能已遭篡 ...

  5. 密码学——网间数据加密传输全流程(SSL加密原理)

    0.导言 昨天写了一篇关于<秘钥与公钥>的文章,写的比较简单好理解,有点儿像过家家,如果详细探究起来会有不少出入,今天就来详细的说明一下数据加密的原理和过程.这个原理就是大名鼎鼎SSL的加 ...

  6. 一篇读懂HTTPS:加密原理、安全逻辑、数字证书等

    1.引言 HTTPS(全称: Hypertext Transfer Protocol Secure,超文本传输安全协议),是以安全为目标的HTTP通道,简单讲是HTTP的安全版.本文,就来深入介绍下其 ...

  7. AES加密解密 助手类 CBC加密模式

    "; string result1 = AESHelper.AesEncrypt(str); string result2 = AESHelper.AesDecrypt(result1); ...

  8. SHA-256 加密原理

    网络中传输敏感信息的时候通常会对字符串做加密解密处理 SHA-256 加密原理

  9. HTTPS加密原理(转)

    Header HTTP.HTTPS在我们日常开发中是经常会接触到的. 我们也都知道,一般 Android 应用开发,在请求 API 网络接口的时候,很多使用的都是 HTTP 协议:使用浏览器打开网页, ...

随机推荐

  1. kongdashboard

    apiVersion: v1kind: Servicemetadata:  name: kong-dashboard  namespace: kongspec:  type: NodePort  po ...

  2. ANSYS 瞬态热分析---零件在水中冷却

    目录 1. 案例 2. APDL分析 1. 案例 一个温度为300℃的铜环和一个温度为200℃的铁环,放置到22℃的水中进行淬火.水桶为铁质的圆形.分析中忽略水的流动. 材料参数 热性能 铜 铁 水 ...

  3. 反射实现定位Servlet中的方法

    public class BaseServlet extends HttpServlet{ @Override protected void service(HttpServletRequest re ...

  4. 第七届蓝桥杯javaB组真题解析-抽签(第五题)

    题目 /* 抽签 X星球要派出一个5人组成的观察团前往W星. 其中: A国最多可以派出4人. B国最多可以派出2人. C国最多可以派出2人. .... 那么最终派往W星的观察团会有多少种国别的不同组合 ...

  5. python 之并发编程更新版进程池与进程池比较与回调函数

    一.更新版进程池与进程池比较 from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor import os, tim ...

  6. Apache Shiro安全(权限框架)学习笔记一

    1. 授权需要继承 AuthorizingRealm 类, 并实现其 doGetAuthorizationInfo 方法 2. AuthorizingRealm 类继承自 Authenticating ...

  7. Python数据类型-3 布尔类型

    布尔类型 对于错.0和1.正与反,都是传统意义上的布尔类型. 但在Python语言中,布尔类型只有两个值,True与False.请注意,是英文单词的对与错,并且首字母要大写,不能其它花式变型. 布尔值 ...

  8. Codeforces 1304D. Shortest and Longest LIS

    根据题目,我们可以找最短的LIS和最长的LIS,找最短LIS时,可以将每一个increase序列分成一组,从左到右将最大的还未选择的数字填写进去,不同组之间一定不会存在s[i]<s[j]的情况, ...

  9. UniGUI之ServerModule常用设置(07)

    主要有两个设置,它是一个单独的, 这意味着它只在每个应用程序中创建一次. 它主要用于配置各种服务器设置.不能将组件放在ServerModule上. 如前所述, ServerModule 是一个单一的, ...

  10. 深度解析Java可变参数类型以及与数组的区别

    注意:可变参数类型是在jdk1.5版本的新特性,数组类型是jdk1.0就有了. 这篇文章主要介绍了Java方法的可变参数类型,通过实例对Java中的可变参数类型进行了较为深入的分析,需要的朋友可以参考 ...