php 弱类型总结

吃可爱长大的小学妹 提交于 2019-11-26 17:05:14

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跟任意字符串在‘==’下成立

 

 

 

 

 

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!