当我们用字符串与数值类型比较时会将字符转变为数值,与C措辞不同的是,他这里并不会转变为ascii码,而是将开头的数字转为对应的数值,开头没有数字则转为0,”0e123456”==”0e456789”相互比较的时候,会将0e这类字符串识别为科学技能法的数字,0的无论多少次方都是零,以是相等。
PHP手册是这么解释的:
当一个字符串欸当作一个数值来取值,其结果和类型如下:如果该字符串没有包含’.’,‘e’,'E’并且其数值值在整形的范围之内 该字符串被当作int来取值,其他所有情形下都被作为float来取值,该字符串的开始部分决定了它的值,如果该字符串以合法的数值开始,则利用该数值,否则其值为0。
0X03弱类型比较的利用1.md5绕过,当传入的参数哈希值为0e开头时有可能触发。2.json绕过,当我们不知道键的名字时可以考试测验传入0,考试测验能否知足形似0==“admin”3.array_search is_array绕过。4.strcmp漏洞绕过,哀求PHP版本<5.3
0X04总结正如所说,我们和开拓最大的不同便是学习这些冷门的奇技淫巧。还有便是,代码功底正是很主要,后悔摧残浪费蹂躏了前两年,走马不雅观花式学习,现在开始恶补java和PHP。末了附上一句正在某互联网大厂做PM的前辈对我说过得的话:互联网是现在为数不多的可以靠努力改变现状的机会,年轻的时候不拼一把,切实其实是摧残浪费蹂躏。
耳听为虚,眼见为实,用代码说话1.MD5绕过<?phpuse phpDocumentor\Reflection\Types\Null_;header('Content-type:text/html;charset=utf-8');show_source(__FILE__);?><html><body><title>md5绕过</title><meta charset="utf-8"></body><body><form method="POST">Str1:<input type="text" name="str1"><br>Str2:<input type="text" name="str2"><br><input type="submit" value="提交"></form></body></html><?php$var1 = $_POST["str1"];$var2 = $_POST["str2"];if (isset($var1) && isset($var2) && $var1 !== Null && $var2 !== Null) {if (md5($var1) == md5($var2)) {echo ("bypass success!!!<br>");echo ("md5_1 = " . md5($var1) . "<br>");echo ("md5_2 = " . md5($var2));} else {echo ("sorry,please hack me again!");}}
这边传入的值不一样,md5值也不同但是都是0exxxxxx格式的,在比较前做类型转换时会被当作科学计数法值为0以是bypass成功
2.json绕过<html><head><title>json绕过</title><meta charset="uft-8"></head><body><form method="POST">message:<input type="test" name="message"><input type="submit" name="提交"></form></body></html><?phpshow_source(__FILE__);header('Content-type:text/html;charset="utf-8"');if (isset($_POST['message'])) {$message = json_decode($_POST['message']);$key = "admin";if ($message->key == $key) {echo "success";} else {echo "fail";}}
输入一个数组进行json解码,如果解码后的message与key值相同,会得到flag,紧张思想还是弱类型进行绕过,我们不知道key值是什莫,但是我们知道一件事便是它肯定是字符串,这样就可以了,上文讲过,两个等号时会转化成同一类型再进行比较,直接布局一个0就可以相等了。终极payload message={“key”:0}
3.array_search is_array绕过<?phpif(!is_array($_GET['test'])){exit();}$test=$_GET['test'];for($i=0;$i<count($test);$i++){if($test[$i]==="admin"){echo "error";exit();}$test[$i]=intval($test[$i]);}if(array_search("admin",$test)===0){echo "flag";}else{echo "false";}?>
这段代码的意思便是先判断是不是数组,然后在把数组中的内容一个个进行遍历,所有内容都不能即是admin,类型也必须相同,然后转化成int型,然后再进行比较如果填入值与admin相同,则返回flag,如何绕过呢?
基本思路还是不变,由于用的是三个即是号,以是说“= =”号这个方法基本不能用,那就用第二条思路,利用函数接入到了不符合的类型返回“0”这个特性,直接绕过检测。以是payload:test[]=0。
在PHP手册中,in_array()函数的阐明是bool in_array ( mixed needle,arrayhaystack [, bool strict=FALSE]),如果strict参数没有供应或者是false(true会进行严格的过滤),那么inarray就会利用疏松比较来判断needle是否在$haystack中。当strince的值为true时,in_array()会比较needls的类型和haystack中的类型是否相同。
$array=[0,1,2,'3'];var_dump(in_array('abc', $array)); //truevar_dump(in_array('1bc', $array)); //true
4.strcmp漏洞绕过(PHP版本<5.3)
<?phpshow_source(__FILE__);error_reporting(0);$var1 = $_REQUEST['string1'];$var2 = $_REQUEST['string2'];echo ("String1:" . $var1 . " " . "type:" . gettype($var1));?><br><?phpecho ("String2:" . $var2 . " " . "type:" . gettype($var2));`?><br><?php$bool = strcmp($var1, $var2);if ($bool < 0) {echo $bool . '<br>';echo ("str1<str2");} elseif ($bool == 0) {echo $bool . '<br>';echo ("str1=str2");} else {echo $bool . '<br>';echo ("str1>str2");}
语法:strcmp(string1,string2)
返回值:0 - 如果两个字符串相等0 - 如果 string1 小于 string20 - 如果 string1 大于 string2漏洞:在PHP5.3之前,传入非String类型的会返回0,即相等。
为了回馈读者,我整理了一些CTF干系的资源供大家阅读,须要的关注我,私信回答“资料”获取更多网络安全架构资料!
!
末了,感谢大家的阅读和关注!
!
!