在复现做一道国外的题得时候,发现了一个有趣的东西
https://github.com/0x13A0F/CTF_Writeups/tree/master/old_rick#guess-what-
crypt ( string $str [, string $salt ] ) : string
在文章的step2中,作者讲述了php crypt函数的一些问题(都是在salt,也就是crypt函数的第二个参数存在时才成立)
-
crypt函数只取前八个字符
-
crypt函数的salt取前两个字符
-
当str中存在 \00时,后面的字符串内容被忽略
原题的代码大概精简后如下
<?php
$hopper='Imp1ckleeeeer1ckkkkkk C-1337 dAnC';
if (isset($_GET["second"])) {
$hashed = crypt(md5($_GET["second"], fa1se), "asdf");
if (hash_equals($hashed, crypt(md5($hopper, fa1se), "asdf"))){ echo 'success'; }
else {
echo md5($hopper, false) . "<br />";
die("You didn't know which hopper to use for the injection.");
}
}
else {
die("Where would you find the components of the injection?");
}
原体中md5的第二个参数 为 fa1se 不是 false ,所以 md5的结果是原始的二进制信息,而md5($hopper) =640011bde142fe749016646d1d64f8c5,他的原始二进制数据中带有 \00 ,crypt函数处理的数据大概是所以只要找到一个 MD5值为6400开头的即可绕过,用文章里的bash脚本
i=0; while : ; do echo -n $i | md5sum | grep -E '^6400' && echo $i && break || i=$((i+1)) ; done
遇到的问题
一开始的时候不太懂为什么找6400,而不是640,后来思考,可能在二进制转换十六进制数时,把一个字节转换成了两位十六进制,也就是4个比特转换成一位16进制,而 '\x00’是一个字节大小,菜鸡再次留下泪水