CTF_Web:php弱类型绕过与md5碰撞

0x00 前言

md5碰撞只是一种掌握php弱类型的方式,弱类型的内容有很多,数组、字符串比较等等,但不论以哪种方式考,涉及的知识点都是相通的,希望通过对基础知识的分享与大家一同学习进步。

0x01 什么是md5

“MD5,即消息摘要算法(英语:MD5 Message-Digest Algorithm)。是一种被广泛使用的密码散列函数,将数据(如一段文字)运算变为另一固定长度值,是散列算法的基础原理,可以产生出一个128位(16字节)的散列值(hash value),用于确保CTF_Web:php弱类型绕过与md5碰撞

由于php中的md5默认返回32字节的结果,所以要得到16字节的需要使用字符串截取。

<?php $str = "hello world!"; echo "32byte-->",md5($str),"<br/>"; //为字符串计算摘要值 $md5Str = substr(md5($str),8,16);//获取16字节的摘要值 echo "16byte-->",$md5Str; ?> 

这是因为32字节的字符串中间8-24字节与16字节加密的结果是相同的,所以在php中我们可以通过这一方式来获得16字节的摘要值。
CTF_Web:php弱类型绕过与md5碰撞

0x02 什么是php弱类型

php是一门弱类型的语言,它不会严格检验变量类型,变量可以不显示地声明其类型,而是在运行期间直接赋值。

在php中比较是否相等有两种符号:=====
其中==在比较时会将不同类型的变量或值转换为相同类型再进行比较。
===则直接比较类型是否相同,如果同类型,再比较值。
那么php弱类型这里的“弱”,指的不是某个类型有什么问题,而是整个php语言中某些函数在处理赋值、字符串比较、变量比较的过程中对类型似乎并不关心,弱化了类型带来的影响,在使用某个变量时不需要我们定义变量的类型,而是根据内容判断这是什么类型,从而导致了各种漏洞的发生。
例如:

<?php var_dump("a"==0);  //true var_dump("1a"==1); //true var_dump("a1"==1); //false var_dump("a1"==0); //true var_dump("0e123456"=="0e234567"); //true var_dump(0=="1a"); //false ?>  

其结果为:

bool(true) bool(true) bool(false) bool(true) bool(true) bool(false)  

上述判断输出的原因是,在php中当一个字符串被当作一个数值来取值时,如果该字符串没有包含'.','e','E',并且其数值值在整形的范围之内时,该字符串被当作int来取值,其他所有情况下都被作为float来取值,而该字符串的开始部分决定了它的值,如果该字符串以合法的数值开始,则使用该数值,否则其值为0。
所以在上面的情况中,1a转换为1a1转换为0,而"0e123456"=="0e234567"相互比较的时候,会将0e这类字符串识别为科学计数法的数字,0的无论多少次方都是零,所以相等。

0x03 md5==绕过(0e比较)

<?php $flag = 'ook!'; $a = $_GET['a']; if ($a != 'QNKCDZO' && md5($a) == md5('QNKCDZO')) {     echo $flag; }else{ echo('你的答案不对0.0'); } 

上面这段代码中就是上述0e开头的所有字串都被认为是0,所以我们先看看md5('QNKCDZO')的结果是0e830400451993494058024219903391,那么所有0e开头的md5串都可以满足上面的条件。
常用的有:

QNKCDZO 0e830400451993494058024219903391 240610708 0e462097431906509019562988736854 s878926199a 0e545993274517709034328855841020 s155964671a 0e342768416822451524974117254469 s214587387a 0e848240448830537924465865611904 

包含了纯数字、纯字母、数字字母组合三种类型的结果,在没有条件限制的情况下,无论使用哪一个都可以成功绕过。在上面的代码中使用?a=240610708,即可打印flag值。

0x04 md5===绕过(数组比较)

在php中的hash函数md5、sha1等处理中若传入一个数组的值,则会报错返回NULL,而返回的值在类型和内容上都是相同的,所以可以用来绕过某些两边参数可控的场景,上面只能控制一边的值传入,所以数组类型不适用。

<?php $flag = "ook!"; $a = $_GET['a']; $b = $_GET['b']; if ($a != $b && md5($a) === md5($b)) //这里==也可以使用数组绕过。 	echo $flag; ?> 

上述的例子中传入?a[]=a&b[]=b即可满足既不相等,md5后又相等的条件,虽然报错,但仍然输出了正确的值。

Warning: md5() expects parameter 1 to be string, array given in 1.php on line 5 Warning: md5() expects parameter 1 to be string, array given in 1.php on line 5 ook! 

0x05 md5===绕过(硬碰撞)

前面我们也提到了md5无论是32位还是16位,都不可能不重复的表示所有信息,这种重复的例子就称为 硬碰撞 ,有如下代码:

<?php $s1 = $_GET['a']; $s2 = $_GET['b']; $s3 = $_GET['c']; echo md5($s1),"<br/>"; echo md5($s2),"<br/>"; echo md5($s3),"<br/>"; ?> 

当传入的值为(url编码后

?a=%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%6d%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%27%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%66%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%96%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%b3%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%ef%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%df%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%73%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%69%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%93%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%28%1c%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%b9%05%39%95%ab &b=%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%6d%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%27%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%66%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%96%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%b3%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%ef%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%5f%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%f3%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%e9%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%13%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%a8%1b%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%39%05%39%95%ab &c=%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%ed%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%a7%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%e6%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%16%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%33%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%6f%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%df%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%73%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%69%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%93%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%28%1c%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%b9%05%39%95%ab 

三个返回相同的md5值,可以通过其有限计算的特性绕过特定的条件。

ea8b4156874b91a4ef00c5ca3e4a4a34 ea8b4156874b91a4ef00c5ca3e4a4a34 ea8b4156874b91a4ef00c5ca3e4a4a34 

0x06 json解码绕过

php在处理传入的json串时使用json_decode将其解码,再进行比较时,我们不需要知道比较字串的内容,也可以利用字符串与0比较为真的特点绕过。

<?php $flag = 'ook!'; $a = $_GET['a']; $b = json_decode($a); echo $b->abc; var_dump($b->abc == $flag); if ($b->abc == $flag)     echo $flag; else 	echo "error!!"; ?> 

当传入?a={"abc":0}时,分别输出

0 bool(true)  ook! 

注意这里的{"abc":0},0是数字,而加双引号{"abc":"0"}之后两边都是字符,就不相等了。

0x07 array_search 绕过

原理都是类型转换的问题,函数的原型为:

mixed array_search ( mixed $needle , array $haystack [, bool $strict = false ] ) 

其中$needle,$haystMrsm1th 师傅的分享,自己动手接受知识会更快。

版权声明:玥玥 发表于 2021-08-10 23:09:16。
转载请注明:CTF_Web:php弱类型绕过与md5碰撞 | 女黑客导航