题目
题目出处:第十七届“控江杯”上海市青少年计算机应用操作竞赛(网络安全对抗赛)
题目类型:Web
题目原地址:http://ctf2017.pengyueisos.com:9080/
Writeup 思路Ⅰ
作者:现代职业技术学校 郭子逸
分析:
由题可知, 我们需要传入两个参数:md5 和md52
条件: md5不为空,md5与md52不相同
两个参数的md5的值和类型相同
根据这个条件,我网络上收到了相关的文章,如下
PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以”0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以”0E”开头的,那么PHP将会认为他们相同,都是0。
在上文中写到,有缺陷的比较方法是'!='和'==',但本题的比较方法'==='不适用,所以不能使用这个方法
我随后查看了php中md5函数的解释,如下
Md5传入的是字符串,如果我传一些别的东西能不能造成失败从而返回FALSE?PHP是弱类型语言,传什么进去好像都会被转换成字符串类型,只有数组成功引起错误,并返回了None。我又写了一个测试用的php,从而证明了我的想法是可行的,如下
error_reporting(0);
$a=['QNKCDZO'];
$b=['s878926199a'];
echo 'a=';
var_dump($a);
echo '
b=';
var_dump($b);
echo '
empty(a) : ';
echo empty($a)?'True':'False';
echo '
empty(b) : ';
echo empty($b)?'True':'False';
echo '
a==b : ';
echo $a != $b?'True':'False';
echo '
md5(a) 类型: ';
echo gettype(md5($a));
echo '
md5(b) 类型: ';
echo gettype(md5($b));
echo '
md5(a) === md5(b): ';
echo md5($a) === md5($b)?'True':'False';
?>
由此可以明白传入
md5[]=任意值
md52[]=任意值
即可得到flag
Writeup 思路Ⅱ
作者:华东师大二附中 何文阳
题目要求给出md5 和md52 两个参数,使得
$_GET['md5'] != $_GET['md52'] && md5($_GET['md5'])===md5($_GET['md52'])
由于md5 的比较用的是===符号,即要求完全相同(类型、数据都相同),要么传入的数据不合法,使得md5 以为输入的都是空字符串;这里讨论另一种思路,即md5 和md52 都是合法数据的情况。
md5 早在2004 年就被王小云破解,并给出了一种有效构造md5 碰撞的算法(可以在一台家用计算机上在1 秒以内随机构造出一组md5 碰撞)。因此在网上可以很容易地找到一组md5碰撞,比如(来自http://www.jianshu.com/p/c9089fd5b1ba):
d131dd02c5e6eec4693d9a0698aff95c
085125e8f7cdc99fd91dbdf280373c5b
d8823e3156348f5bae6dacd436c919c6
e99f33420f577ee8ce54b67080a80d1e
c69821bcb6a8839396f9652b6ff72a70
d131dd02c5e6eec4693d9a0698aff95c
55ad340609f4b30283e4888325f1415a
085125e8f7cdc99fd91dbd7280373c5b
d8823e3156348f5bae6dacd436c919c6
c69821bcb6a8839396f965ab6ff72a70
两组数据的md5 均为79054025255fb1a26e4bc422aef54eb4。
接下来只要把这两组数据输入到get 框中就可以了。这需要使用urlencode,即在浏览器中用一个%符号加两个十六进制数来表示不可打印字符和特殊字符的方法。处理后得到的URL类似这样:
http://ctf2017.pengyueisos.com:9080/?md5=%d1%31%dd%02%c5%e6%ee%c4%69%3d%9a%06%98%af%f9%5c%2f%ca%b5%87%12%46%7e%ab%40%04%58%3e%b8%fb%7f%89%55%ad%34%06%09%f4%b3%02%83%e4%88%83%25%71%41%5a%08%51%25%e8%f7%cd%c9%9f%d9%1d%bd%f2%80%37%3c%5b%d8%82%3e%31%56%34%8f%5b%ae%6d%ac%d4%36%c9%19%c6%dd%53%e2%b4%87%da%03%fd%02%39%63%06%d2%48%cd%a0%e9%9f%33%42%0f%57%7e%e8%ce%54%b6%70%80%a8%0d%1e%c6%98%21%bc%b6%a8%83%93%96%f9%65%2b%6f%f7%2a%70&md52=%d1%31%dd%02%c5%e6%ee%c4%69%3d%9a%06%98%af%f9%5c%2f%ca%b5%07%12%46%7e%ab%40%04%58%3e%b8%fb%7f%89%55%ad%34%06%09%f4%b3%02%83%e4%88%83%25%f1%41%5a%08%51%25%e8%f7%cd%c9%9f%d9%1d%bd%72%80%37%3c%5b%d8%82%3e%31%56%34%8f%5b%ae%6d%ac%d4%36%c9%19%c6%dd%53%e2%34%87%da%03%fd%02%39%63%06%d2%48%cd%a0%e9%9f%33%42%0f%57%7e%e8%ce%54%b6%70%80%28%0d%1e%c6%98%21%bc%b6%a8%83%93%96%f9%65%ab%6f%f7%2a%70
访问即可得到flag
除了md5 外,已知的存在碰撞的加密算法还有md4、SHA-0、SHA-1(见“shattered”;除了shattered.pdf 以外并没有发现其它碰撞的例子)等,而SHA-256 目前仍被认为是安全的。并且,对于任何加密算法,我们仍然可以使用“生日攻击”:假如哈希函数只有n 个bit,则我们可以在2 的n/2 次方的期望复杂度内找到一个碰撞。即使是安全的SHA-256 算法,如果我们只使用SHA-256 函数的前7 个字节,则只有56 个bit,这意味着我们可以在期望O(2^28)的时间和内存内找到一组碰撞,2^28= 268435456,可以在一台家用计算机上用较少的时间求出。
本文系原创!转载请注明出处!
领取专属 10元无门槛券
私享最新 技术干货