php 弱类型总结
特别注意: md5(), json_encode(), array_search(), strcmp(), switch() ,in_array() 这几个容易涉及到php弱类型的函数
描述:php中有两种比较的符号 == 与 ===
=== 在进行比较的时候,会先判断两种字符串的类型是否相等,再比较值是否相等
== 在进行比较的时候,会先将字符串类型转化成相同,再比较值
如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换成数值并且比较按照数值来进行
漏洞关键:
当一个字符串欸当作一个数值来取值,其结果和类型如下:如果该字符串没有包含'.','e','E'并且其数值值在整形的范围之内
该字符串被当作int来取值,其他所有情况下都被作为float来取值,该字符串的开始部分决定了它的值,如果该字符串以合法的数值开始,则使用该数值,否则其值为0。
<?php
2 var_dump("admin"==0); //true
3 var_dump("1admin"==1); //true
4 var_dump("admin1"==1) //false
5 var_dump("admin1"==0) //true
6 var_dump("0e123456"=="0e4456789"); //true
7 ?> //上述代码可自行测试
1 观察上述代码,"admin"==0 比较的时候,会将admin转化成数值,强制转化,由于admin是字符串,转化的结果是0自然和0相等
2 "1admin"==1 比较的时候会将1admin转化成数值,结果为1,而“admin1“==1 却等于错误,也就是"admin1"被转化成了0,为什么呢??
3 "0e123456"=="0e456789"相互比较的时候,会将0e这类字符串识别为科学技术法的数字,0的无论多少次方都是零,所以相等
类型一 :md5 绕过{hash 比较缺陷}
1 <?php
2 if (isset($_GET['Username']) && isset($_GET['password'])) {
3 $logined = true;
4 $Username = $_GET['Username'];
5 $password = $_GET['password'];
6
7 if (!ctype_alpha($Username)) {$logined = false;}
8 if (!is_numeric($password) ) {$logined = false;}
9 if (md5($Username) != md5($password)) {$logined = false;}
10 if ($logined){
11 echo "successful";
12 }else{
13 echo "login failed!";
14 }
15 }
16 ?>
分析:题目大意是要输入一个字符串和数字类型,并且他们的md5值相等,就可以成功执行下一步语句
介绍一批md5开头是0e的字符串 上文提到过,0e在比较的时候会将其视作为科学计数法,所以无论0e后面是什么,0的多少次方还是0。md5('240610708') == md5('QNKCDZO')成功绕过!
1 <?php
2 include_once "flag.php";
3 ini_set("display_errors", 0);
4 $str = strstr($_SERVER['REQUEST_URI'], '?');
5 $str = substr($str,1);
6 $str = str_replace('key', ' ' ,$str);
7 parse_str($str);
8 echo md5($key1);
9 echo md5($key2);
10 if(md5($key1) == md5($key2) && $key1 !== $key2){
11 echo $flag."取得flag";}
12 ?>
分析:简单解释下代码的含义,从URL中'?'后面截取首次获得$str的值,然后截取$str中的第一个字符,返回剩余字符,用空格替换key,输出key1和key2,且的key1和key2的md5值相等,key1的值不等于key2
绕过一:利用md5()函数无法处理数组,如果传入的为数组,会返回NULL,所以两个数组经过加密后得到的都是NULL,也就是相等的。
构造payload:?kkeyey1[]=a&kkeyey2[]=b
绕过二:可以构造:kkeyey1=QNKCDZO&kkeyey2=240610708
实战 2: json 绕过
<?php
if (isset($_POST['message'])) {
$message = json_decode($_POST['message']);
$key ="*********";
if ($message->key == $key) {
echo "flag";
}
else {
echo "fail";
}
}
else{
echo "~~~~";
}
?>
分析:输入一个json类型的字符串,json_decode函数解密成一个数组,判断数组中key的值是否等于 $key的值,但是$key的值我们不知道,但是可以利用0=="admin"这种形式绕过
最终payload message={"key":0}
实战 3 :array_search() 绕过
1 <?php
2 if(!is_array($_GET['test'])){exit();}
3 $test=$_GET['test'];
4 for($i=0;$i<count($test);$i++){
5 if($test[$i]==="admin"){
6 echo "error";
7 exit();
8 }
9 $test[$i]=intval($test[$i]);
10 }
11 if(array_search("admin",$test)===0){
12 echo "flag";
13 }
14 else{
15 echo "false";
16 }
17 ?>
分析:上面是自己写的一个,先判断传入的是不是数组,
然后循环遍历数组中的每个值,并且数组中的每个键值不能和admin相等,
并且将每个值转化为int类型,
再判断传入的数组是否有“admin”,有则返回flag
payload test=[0]可以绕过
array_search() 函数与 in_array() 一样,在数组中查找一个键值。如果找到了该值,则返回匹配该元素所对应的键名。如果没找到,则返回 false
原因:array_serch() 在判断数组里面有没有 键值与 字符串“admin”相等 的 用的是 == ,根据php弱类型,字符串admin 的值为 0 ,所以构造一个含有0索引位置的键值为0 的数组 test 就可以成功绕过
实战 4 strcmp()绕过
1 <?php
2 $password="***************"
3 if(isset($_POST['password'])){
4
5 if (strcmp($_POST['password'], $password) == 0) {
6 echo "Right!!!login success";n
7 exit();
8 } else {
9 echo "Wrong password..";
10 }
11 ?>
分析:strcmp是比较两个字符串,如果str1<str2 则返回值<0 ,如果str1大于str2返回>0 ,如果两者相等 返回0
我们是不知道$password的值的,题目要求strcmp判断的接受的值和$password必需相等,strcmp传入的期望类型是字符串类型,如果传入的是个数组会怎么样呢
我们传入 password[]=xxx 可以绕过 是因为函数接受到了不符合的类型,将发生错误,但是还是判断其相等
payload: password[]=xxx
实战 5:switch()绕过
1 <?php
2 $a="4admin";
3 switch ($a) {
4 case 1:
5 echo "fail1";
6 break;
7 case 2:
8 echo "fail2";
9 break;
10 case 3:
11 echo "fail3";
12 break;
13 case 4:
14 echo "sucess"; //结果输出success;
15 break;
16 default:
17 echo "failall";
18 break;
19 }
20 ?>
分析 : 在进行switch 选择时 $a会被强制转换成整形进行对照
所以 令$a="4asdfs" =int(4)成功进行绕过
实战6:in_array()函数
in_array() 的定义是 bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] ),如果strict参数没有提供,那么in_array就会使用松散比较来判断 $needle 是否在 $haystack 中。当 $strict 的值为 true 时,in_array() 会比较 $needls 的类型和 $haystack 中的类型是否相同。如下:
$array = [0, 1, 2, '3'];
in_array('abc', $array); # true
in_array('1bc', $array); # true
实战7: 成也布尔,败也布尔;
成也布尔,败也布尔‘,布尔类型的true跟任意字符串在‘==’下成立
来源:https://blog.csdn.net/vhkjhwbs/article/details/89387850