回头看第一次打CTF的南宁杯-PHP弱类型比较

前言

​ 南宁杯是我第一次打CTF比赛,当时PHP基础比较薄弱,回头看看几题。

<?php
$white_list = range(0, 9);
require_once ('flag.php');
if (isset($_REQUEST['no'])) {
    $a = $_REQUEST['no'];
    if (@ereg("^[0-9]+$", $a) === FALSE) {
        echo 'no must be number';
    } else {
        if (in_array($a, $white_list)) {
            if (strlen($a) > 1) {
                echo 'you are a great dark phper<br>';
                echo "<img src='dark.gif'><br>";
                echo $flag;
            } else {
                echo 'you no dark';
            }
        } else {
            echo 'you are so dark';
        }
    }
}
else
    highlight_file(__FILE__);
?>

  • 题目解析

    当时是解出来这道题了,但是并没有懂得其中原理,我当时的payload是?no=1%00--0,2,3,4,5,6,7,8,9当时我以为是我传进来一个数组然后通过了 比较,但是其实并不是这样的,我传进去的仍然是一个字符串,但是为什么能够通过比较呢?这里in_array存在一个弱类型比较的问题,in_array存在三个参数:

    mixed:类型 支持做种复合类型,参数传入也是可以是int,str,float,array 
    
    haystack:  源数组,查找的数组。
    
    strict : 参数接受两个 true 和false 两个参数.该参数主要检查 $needle  和$haystack  中的value 的类型是否一致。

    ​ 如果第三个参数没使用true的话那么就会进行比较宽松的比较, 由于 PHP 是弱类型语言,在对两个不同类型的值进行操作(比较运算)时,会存在数据类型的 隐式转化。 那么我插入%00应该相当于1+空格,那么字符串长度就会大于1这样就会绕过大于一的限制,但是同时后面加入任何数都会转化为同类型进行比较,string类型全部转化为0那么也能够通过比较。这里相当于,‘a'==’0?==>0==0,但是为什么用%00这是因为ereg函数存在一个截断的漏洞。这样可以直接绕过这个函数的检测。当然另外一个payload也可以通过检测:?no=01原因相似

    延伸-PHP弱类型比较

    strcmp()函数

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

    这里其实存在一个漏洞,strcmp()函数其实本质是将字符串转化为ASCII码再相减作,如果相减为0那么就是通过匹配,但是这里如果传入的的值并不是字符串类型同样会返回FLASE(0)进而通过比较,那么最后的payloadpassword[]=0.

    switch()函数

    <?php
    $i ="3name";
    switch ($i) {
    case 0:
    case 1:
    case 2:
         echo "this is two";
         break;
    case 3:
         echo "flag";
    break;
    }
    ?>

    这里其实,switch()函数在进行case比较时候回将传入的字符串转化为整数型再进行比较。所以最终输出的是flag,这里和intval()一致。

    MD5() 、sha1()

    <?php
    if (isset($_POST['a']) and isset($_POST['b'])) {
    if ($_POST['a'] != $_POST['b'])
    if (md5($_POST['a']) === md5($_POST['b']))
    die('Flag: '.$flag);
    else
    print 'Wrong.';
    }
    ?>

    这两个函数在本次海啸杯也考察到了,不能处理数组,传入两个数组即可将其绕过。

    json

    <?php
    if (isset($_POST['message'])) {
        $message = json_decode($_POST['message']);
        $key ="*********";
        if ($message->key == $key) {
            echo "flag";
        }
        else {
            echo "fail";
        }
    }
    else{
         echo "~~~~";
    }
    ?>

    其实这个本质也是弱类型比较。只需构造message={'key':0}

    十六进制比较问题

    <?php
    function noother_says_correct($number)
    {
           $one = ord('1');
           $nine = ord('9');
           for ($i = 0; $i < strlen($number); $i++)
           {  
                   $digit = ord($number{$i});
                   if ( ($digit >= $one) && ($digit <= $nine) )
                   {
                           return false;
                   }
           }
              return $number == '54975581388';
    }
    $flag='*******';
    if(noother_says_correct($_GET['key']))
       echo $flag;
    else
       echo 'access denied';
    ?>

    这道题的意思就是要求输入一个key,然后这个key必须等于54975581388但是在自定义的函数里面又不允许出现数字,正好54975581388=0xccccccccc这样就绕过了检测。

    HASH比较操作符问题

    "0e132456789"=="0e7124511451155" //true
    "0e1abc"=="0"     //true4219903

    上面的比较确实会通过,那么为什么呢,在比较的时候,当出现xex模式,即匹配:0e\d+的 字符串将会当做科学计数法进行比较。

    <?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!";
             }
         }
     ?>

    payload:md5('240610708') == md5('QNKCDZO')

本文总阅读量
× 文章目录
  1. 1. 前言
  2. 2. 延伸-PHP弱类型比较
    1. 2.0.0.1. strcmp()函数
    2. 2.0.0.2. switch()函数
    3. 2.0.0.3. MD5() 、sha1()
  • 2.1. json
    1. 2.1.0.1. 十六进制比较问题
  • 2.2. HASH比较操作符问题