今天看到这样一道题

<!-- please login as uid=1!--> 
<?php 
include("AES.php"); 
highlight_file('index.php');     
$v = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890auid=9;123123123123"; 
$b = array(); 
$enc = @encrypt($v); 
$b = isset($_COOKIE[user])?@decrypt(base64_decode($_COOKIE[user])):$enc; 
$uid = substr($b,strpos($b,"uid")+4,1); 
echo 'uid:'.$uid.'<br/>'; 
if ($uid == 1){ 
        echo $flag; 
} 
else { 
        echo "Hello Client!"; 
} 
setcookie("user",base64_encode($enc)); 
?> 
uid:9
Hello Client!

大致的做法就是控制$b里面包含uid=1,但是因为加密密钥不知道,所以并不能控制,后来发现这个是利用了 CBC 密文分组的一个问题。

CBC 模式的全称是密文分组链接模式(Cipher Block Chainning)。在CBC模式中,首先将明文分组与前一个密文分组进行 xor 运算,然后再进行加密,当加密第一个明文分组时,由于不存在“前一个密文分组”,因此需要事先准备一个长度为一个分组的比特序列来代替“前一个密文分组”,这个比特序列称为初始化向量(Initialization vector),通常缩写为 IV,如果每次都使用相同的初始化向量(IV),当用同一密钥对同一明文进行加密时,所得到的密码一定是相同的,所以每次加密时都会随机产生一个不同的比特序列来作为初始化向量,避免这种情况产生。

见示意图

2015022703012929473.png

这样的话,解密的时候是本组的明文与上一组的密文进行反 xor 操作就可以了,如果我们控制了上一组的密文,那就可以控制本组的明文了。

首先将明文分组

1234567890abcdef
1234567890abcdef
1234567890abcdef
1234567890auid=9
;123123123123

根据之前的算法原理,以第4组为例,设 A = 第四组解密后的值、B = 第三组的密文,则 C = A xor B -> “1234567890auid=9”

这样的话,就可以反推得到 A = B xor C,很容易就写出反向的公式

<?php
$enc = base64_decode("S9PsFp43k9VgyrggRHLbISjUAjwzSSPPajrF9Dzz0o/ieSZbxwGjTJ5xhAZEi5tDBjvwsQtH0BynlLC0p0F0zOZMx25M6iekcLvX//MNKSA=");
$enc[47] = chr(ord($enc[47]) ^ ord("9") ^ ord ("1"));
echo base64_encode($enc);
?>

然后提交就好了

QQ20160109-4.png

参考 http://drops.wooyun.org/tips/7828