zoukankan      html  css  js  c++  java
  • 2020/2/3 PHP代码审计之PHP弱类型

    0x00 简介

    php中有两种比较的符号 == 与 ===

    <?php
    2 $a = $b ;
    3 $a===$b ;
    4 ?>
    

    === 在进行比较的时候,会先判断两种字符串的类型是否相等,再比较

    == 在进行比较的时候,会先将字符串类型转化成相同,再比较

    如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换成数值并且比较按照数值来进行

    0x01 变量类型

    标准类型:布尔 boolen,整型 integer,浮点 float,字符 string
    复杂类型:数组 array,对象 object
    特殊类型:资源 resource

    0x02 操作之间的比较

    1:字符串和数字比较
    2:数字和数组的比较
    3:字符串和数组比较
    4:“合法数字+e+合法数字”类型的字符串。
    5:=

    0x03字符串和数字比较

    <?php
    var_dump("admin"==0);  //true
    var_dump("1admin"==1); //true
    var_dump("admin1"==1) //false
    var_dump("admin1"==0) //true
    var_dump("0e123456"=="0e4456789"); //true 
    ?>  //上述代码可自行测试
    
    1 观察上述代码,"admin"==0 比较的时候,会将admin转化成数值,强制转化,由于admin是字符串,转化的结果是0自然和0相等
    
    
    2 "1admin"==1 比较的时候会将1admin转化成数值,结果为1,而“admin1“==1 却等于错误,也就是"admin1"被转化成了0,为什么呢??
    
    
    
    

    当一个字符串欸当作一个数值来取值,其结果和类型如下:如果该字符串没有包含'.','e','E'并且其数值值在整形的范围之内该字符串被当作int来取值,其他所有情况下都被作为float来取值,该字符串的开始部分决定了它的值,如果该字符串以合法的数值开始,则使用该数值,否则其值为0.

    0x04 数字和数组的比较

    <?php
     $arr = array();
     var_dump(0==$arr);//false
    
    ?>
    
    

    0x05 字符串和数组比较

    0x06 合法数字+e+合法数字”类型的字符串。

    var_dump("0e123456"=="0e4456789"); //true 
    

    "0e123456"=="0e456789"相互比较的时候,会将0e这类字符串识别为科学技术法的数字,0的无论多少次方都是零,所以相等

     var_dump("1e1:=="10")//true
    

    10的一次方还是10

    0x07 函数之 empty 和 isset

    1)变量为:0,"0", null, '', false,array() 时,使用 empty 函数,返回
    2)变量未定义或者为 null 时,isset 函数返回的为 false ,其他都为 true

    0x08 函数之 md5

    <?php
    if (isset($_GET['Username']) && isset($_GET['password'])) {
        $logined = true;
        $Username = $_GET['Username'];
        $password = $_GET['password'];
    
         if (!ctype_alpha($Username)) {$logined = false;}
         if (!is_numeric($password) ) {$logined = false;}
         if (md5($Username) != md5($password)) {$logined = false;}
         if ($logined){
        echo "successful";
          }else{
               echo "login failed!";
            }
        }
    ?>
    

    题目大意是要输入一个字符串和数字类型,并且他们的md5值相等,就可以成功执行下一步语句
    介绍一批md5开头是0e的字符串 上文提到过,0e在比较的时候会将其视作为科学计数法,所以无论0e后面是什么,0的多少次方还是0。md5('240610708') == md5('QNKCDZO')成功绕过!
    这里顺便提一下有个md5快速碰撞工具fastcoll,它可以生成两个MD5值相同的不同文件。

    fastcoll_v1.0.0.5.exe -o a b

    QNKCDZO
    0e830400451993494058024219903391
    
    s878926199a
    0e545993274517709034328855841020
      
    s155964671a
    0e342768416822451524974117254469
      
    s214587387a
    0e848240448830537924465865611904
      
    s214587387a
    0e848240448830537924465865611904
      
    s878926199a
    0e545993274517709034328855841020
      
    s1091221200a
    0e940624217856561557816327384675
      
    s1885207154a
    0e509367213418206700842008763514
    

    解释:
    PHP手册中的 md5() 函数的描述是 string md5 ( string $str [, bool $raw_output = false ] ) ,md5() 中需要的是一个 string 类型的参数。但是当你传递一个 array 时,md5() 不会报错,只是会无法正确地求出 array 的 md5 值,这样就会导致任意 2 个 array 的 md5 值都会相等。

    0x09 函数之 strcmp 漏洞绕过( php -v < 5.3 )

    strcmp 是比较两个字符串,如果 str1 < str2 则返回 <0 如果 str1 大于 str2 返回 >0 如果两者相等则返回 0

    <?php
        $password="***************"
         if(isset($_POST['password'])){
    
            if (strcmp($_POST['password'], $password) == 0) {
                echo "Right!!!login success";n
                exit();
            } else {
                echo "Wrong password..";
            }
    ?>
    

    我们是不知道 $password 的值的,题目要求 strcmp 判断的接受的值和 $password 必需相等,strcmp 传入的期望类型是字符串类型,如果传入的是个数组会怎么样呢
    我们传入 password[]=xxx 可以绕过,是因为函数接受到了不符合的类型,将发生错误,但是还是判断其相等

    payload: password[]=xxx
    
    <?php
    if(!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

    payload test[]=0可以绕过
    

    在 PHP 手册中,in_array() 函数的解释是 bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] ) ,如果 strict 参数没有提供,那么 in_array 就会使用松散比较来判断 $needle 是否在 $haystack 中。当 strince 的值为 true 时,in_array() 会比较 needls 的类型和 haystack 中的类型是否相同。

    array_search() 函数在数组中搜索某个键值,并返回对应的键名。官方手册对 array_search 的介绍: mixed array_search ( mixed $needle , array $haystack [, bool $strict = false ] ) 其中 $needle,$haystack 必需,$strict 可选 函数判断 $haystack 中的值是存在 $needle,存在则返回该值的键值第三个参数默认为 false ,如果设置为 true 则会进行严格过滤

    0x11 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)成功进行绕过

    参考链接:
    https://cloud.tencent.com/developer/article/1180452

  • 相关阅读:
    python数据类型三(字典)
    python数据类型二(列表和元组)
    python数据类型一(重点是字符串的各种操作)
    python基础二
    jquery validate学习心得
    Block 朴实理解
    Block 使用场景
    Block 进阶
    MD5加密
    SQL语句中 chinese_prc_CS_AI_WS 以及replace用法
  • 原文地址:https://www.cnblogs.com/wangtanzhi/p/12255061.html
Copyright © 2011-2022 走看看