CBC字节翻转攻击

CBC翻转攻击方法在于:

通过损坏密文字节来改变明文字节。(注:借助CBC内部的模式)借由此可以绕过过滤器,或者改变用户权限提升至管理员,又或者改变应用程序预期明文以达目的。

CBC模式介绍

加密过程

图片.png

Plaintext:明文数据,待加密的数据

IV:初始向量,用于随机化加密的比特块,保证即使对相同明文多次加密,也可以得到不同的密文。

Key:分组加密使用的密钥,被一些如AES的对称加密算法使用。

Ciphertext:密文数据,加密后的数据。

明文都是先与混淆数据(第一组是与IV,之后都是与前一组的密文)进行异或,再执行分组加密的。CBC工作于一个固定长度的比特组,将其称之为块

步骤:

  1. 首先将明文分组(常见的以16字节为一组),位数不足的使用特殊字符填充。
  2. 生成一个随机的初始化向量(IV)和一个密钥。
  3. 将IV和第一组明文异或。
  4. 用密钥对3中xor后产生的密文加密。
  5. 用4中产生的密文对第二组明文进行xor操作。
  6. 用密钥对5中产生的密文加密。
  7. 重复4-7,到最后一组明文。
  8. 将IV和加密后的密文拼接在一起,得到最终的密文。

从第一块开始,首先与一个初始向量iv异或(iv只在第一处作用),然后把异或的结果配合key进行加密,得到第一块的密文,并且把加密的结果与下一块的明文进行异或,一直这样进行下去。因此这种模式最重要的特点就是:前一块的密文用来产生后一块的密文。
加密公式:

Ciphertext-0 = Encrypt(Plaintext XOR IV)—只用于第一个组块
Ciphertext-N = Encrypt(Plaintext XOR Ciphertext-N-1)—用于第二及剩下的组块

解密过程

图片.png

解密的过程其实只要理解了加密,反过来看解密过程就也很简单了,同样的,前一块密文参与下一块密文的还原。
步骤:
1. 从密文中提取出IV,然后将密文分组。
2. 使用密钥对第一组的密文解密,然后和IV进行xor得到明文。
3. 使用密钥对第二组密文解密,然后和2中的密文xor得到明文。
4. 重复2-3,直到最后一组密文。

解密公式:

Plaintext-0 = Decrypt(Ciphertext) XOR IV—只用于第一个组块
Plaintext-N = Decrypt(Ciphertext) XOR Ciphertext-N-1—用于第二及剩下的组块

这里可以注意到Ciphertext-N-1用来产生下一块明文,如果我们改变Ciphertext-N-1中的一个字节,然后和下一块解密后的密文xor,就可以得到一个不同的明文,而这个明文是我们可以控制的。利用这一点,我们就欺骗服务端或者绕过过滤器。
下图展示了整个攻击过程:


图片.png

解析


图片.png

根据解密流程,我们假设A为明文,B为前一组密文,C为密文经过AES解密后的字串:
A = Plaintext[0] = 11
B = (Ciphertext-N-1)[0] = 13
C = Decrypt(Ciphertext)[0] = 6

我们可以知道,解密过程中是C与B异或得到A,即A xor B = C。

那么关键来了

C xor C = 0 (任何数与自己异或都为0)
等价于
A xor B xor C = 0

由于任何数与0异或都为自己本身,所以

A xor B xor C xor 3 = 3

那么此时我们其实可以这样来看:

A = A = 11
B = B xor 3 = 13 xor 3 = 14
C = C = 6

现在我们修改密文对应的位让B = 14,那么当密文解密后,会发现,明文A会变成3,通过这种方法我们可以控制任何一位明文。

php使用异或xor调换两个变量的值的原理

1、首先,我们要知道什么是异或,异或,简单来说就是:相同的两个数,异或的结果是0;不同的两个数,异或的结果是1。
2、0和0,异或的结果是0。1和1,异或的结果是0。0和1,异或的结果是1。于是我们发现,在0和1的世界里:A和B异或,结果是C;B和C异或的结果一定是A;A和C异或的结果一定是B。
3、写成php:

$a = 0;
$b = 1;
$c = $a ^ $b; //A和B异或,结果是C
$b = $b ^ $c; //B和C异或的结果一定是A,将A赋值给B
$a = $b ^ $c; //A(原A,现B)和C异或的结果一定是B,将B赋值给A
echo $a,$b; //已经实现$a和$b的值对调

4、a和b是二进制的一位数,如此;是多位数,也是如此。
于是:

$a = 3; //0011
$b = 4; //0100
$c = $a ^ $b; //A和B异或,结果是C
$b = $b ^ $c; //B和C异或的结果一定是A,将A赋值给B
$a = $b ^ $c; //A(原A,现B)和C异或的结果一定是B,将B赋值给A
echo $a,$b; //已经实现$a和$b的值对调

5、a和b如果是字母,也可以:

$a = 'a'; //ASCII是97,二进制是0110 0001
$b = 'b'; //ASCII是98,二进制是0110 0010
$c = $a ^ $b; //A和B异或,结果是C
$b = $b ^ $c; //B和C异或的结果一定是A,将A赋值给B
$a = $b ^ $c; //A(原A,现B)和C异或的结果一定是B,将B赋值给A
echo $a,$b; //已经实现$a和$b的值对调

能够成功将两个字符串变量调换,原因就在于:两个变量进行异或时,会将字符串转换成二进制再进行异或,异或完,又从二进制转换成了字符串。

本文参考:http://www.ifuryst.com/archives/CBC_bitflipping_attacks.html
https://blog.csdn.net/csu_vc/article/details/79619309
https://blog.csdn.net/jeffreynnn/article/details/77100389
http://www.freebuf.com/articles/system/163756.html

你可能感兴趣的:(CBC字节翻转攻击)