0x00前言
web有关CBC的题偶尔就出现,老是忘,要经常复习QWQ,这里总结一下翻字节攻击
0X01 分析
CBC解密过程:
需要知道的点
aes-cbc 是分组加密,一般16个字节一组一块,iv也为16字节
中间值是指密文块解密之后的数据
iv会与第一组中间值异或最后得到明文,往后则是每一组的密文与下一组的中间值
例如iv的第5位改变,那么第一组解密明文的第五位也会被改变
往后则是,如果第一组密文的第5位改变,就会影响到第二组解密出来的明文的第5位(16位一组就是第21位被改了),以此类推
0x02测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| <?php
define("METHOD","aes-128-cbc"); define("SECRET_KEY", "17a8922b-11c1-11ea-bace-f430b9537591");
function get_random_token(){ $random_token=''; for($i=0;$i<16;$i++){ $random_token.=chr(rand(1,255)); } return $random_token; } $iv = get_random_token(16); $info = '{"role_id":3,"user_id":1,"name":"tinmin"}'; $c = openssl_encrypt($info, METHOD, SECRET_KEY, OPENSSL_RAW_DATA,$iv );
echo "cipher: ".base64_encode($c).PHP_EOL; echo "iv: ".base64_encode($iv ).PHP_EOL;
$newiv1 = $iv; $newiv1[11] = $iv[11] ^ '1' ^ '3'; echo "plain: ".openssl_decrypt($c,METHOD,SECRET_KEY,OPENSSL_RAW_DATA,$newiv1 ).PHP_EOL;
$c[8] = $c[8] ^ '1' ^ '3'; $plain = openssl_decrypt($c,METHOD,SECRET_KEY,OPENSSL_RAW_DATA,$iv ); echo "plain: ".$plain.PHP_EOL; $group1 = '{"role_id":1,"us'; $newiv2 = "";
for($i=0;$i<strlen($group1);$i++){ $newiv2 .= $group1[$i] ^ $iv[$i] ^ $plain[$i]; } echo "plain: ".openssl_decrypt($c,METHOD,SECRET_KEY,OPENSSL_RAW_DATA,$newiv2 ).PHP_EOL;
|
分组情况:
1 2 3
| {"role_id":3,"us er_id":1,"name": "tinmin"}
|
修改第一组
第一次为了修改role_id
,将其修改为1,数了一下,它是第12位,于是修改iv的第12位
我们知道
我们知道原来的值为3,那么就有
1
| $iv[11] = $iv[11] ^ '1' ^ '3';
|
解密出来
1
| {"role_id":1,"user_id":1,"name":"tinmin"}
|
可可可
修改第二组
第二次为了修改user_id
,将其修改为3,数了一下,它是第23位,是第二组的第8位,于是修改第一组密文的第8位
就有
1
| $c[8] = $c[8] ^ '1' ^ '3';
|
解密出来前面乱码
1
| F���9f� �er_id":1."name":"tinmin"}
|
为了恢复正常,我们要修改iv,来达到修改第一组密文的目的
目标字符串为
生成新的iv
1 2 3 4
| $newiv2 = ""; for($i=0;$i<strlen($group1);$i++){ $newiv2 .= $group1[$i] ^ $iv[$i] ^ $plain[$i]; }
|
解密
1
| {"role_id":1,"user_id":1."name":"tinmin"}
|
正常了