• PHP代码审计分段讲解(3)


    05 ereg正则%00截断

    放上源代码

    <?php 
    
    $flag = "flag";
    
    if (isset ($_GET['password'])) 
    {
      if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE)
      {
        echo '<p>You password must be alphanumeric</p>';
      }
      else if (strlen($_GET['password']) < 8 && $_GET['password'] > 9999999)
       {
         if (strpos ($_GET['password'], '*-*') !== FALSE) //strpos — 查找字符串首次出现的位置
          {
          die('Flag: ' . $flag);
          }
          else
          {
            echo('<p>*-* have not been found</p>'); 
           }
          }
         else 
         {
            echo '<p>Invalid password</p>'; 
          }
       } 
    ?>

    查看代码流程,使用GET方式传入password,然后使用ereg函数进行正则匹配

    关于ereg函数有:

    以区分大小写的方式在 string 中寻找与给定的正则表达式 pattern 所匹配的子串。

    如果找到与 pattern 中圆括号内的子模式相匹配的子串并且函数调用给出了第三个参数 regs,则匹配项将被存入 regs 数组中。$regs[1] 包含第一个左圆括号开始的子串,$regs[2] 包含第二个子串,以此类推。$regs[0] 包含整个匹配的字符串。

    然而ereg函数是一个存在缺陷的函数,现在大都使用preg_match函数对其替换,其缺陷在于:当ereg()函数碰到%00的时候,就会认为字符串结束了,并不会继续向下检测,另外当其碰到数组的时候返回为NULL

    接着是:

    else if (strlen($_GET['password']) < 8 && $_GET['password'] > 9999999)

    需要password长度小于8并且大于9999999,这个可以直接使用科学计数法绕过,即1e9这种

    获取flag需要满足:

    if (strpos ($_GET['password'], '*-*') !== FALSE) //strpos — 查找字符串首次出现的位置

    即在password里面能够找到字符串

    *-*

    想要找到该字符串,就需要突破第一个if的限制,这里我们使用到的就是%00截断

    最终的payload为:

    ?password=1e9%00*-*

    成功获取flag

     

    06 strcmp比较字符串

    源代码为:

    <?php
    $flag = "flag";
    if (isset($_GET['a'])) {  
        if (strcmp($_GET['a'], $flag) == 0) //如果 str1 小于 str2 返回 < 0; 如果 str1大于 str2返回 > 0;如果两者相等,返回 0。 
    
        //比较两个字符串(区分大小写) 
            die('Flag: '.$flag);  
        else  
            print 'No';  
    }
    
    ?>

    这里需要我们以GET方式传入a,并且比较a和$flag是否相等,相等则输出flag

    这个逻辑看似是锁死了我们的路,我们想要知道flag才来做题,但是做这个题获取flag需要已知flag :D

    查看代码,可以看到比较两者大小使用的是strcmp函数,而该函数是存在漏洞的

    关于strcmp函数

    定义和用法

    strcmp() 函数比较两个字符串。

    注释:strcmp() 函数是二进制安全的,且对大小写敏感。

    该函数比较两个字符串,而要是我们传入的不是字符串呢?

    输入非字符串的时候,函数会出现报错,但是函数返回0,也就是说,虽然函数报错了,但是判断结果却是相等

    所以最后的payload为

    ?a[]=1

    07 sha()函数比较绕过

    源代码为

    <?php
    
    $flag = "flag";
    
    if (isset($_GET['name']) and isset($_GET['password'])) 
    {
        if ($_GET['name'] == $_GET['password'])
            echo '<p>Your password can not be your name!</p>';
        else if (sha1($_GET['name']) === sha1($_GET['password']))
          die('Flag: '.$flag);
        else
            echo '<p>Invalid password.</p>';
    }
    else
        echo '<p>Login first!</p>';
    ?>

    可以看到我们需要使用GET方式传入name和password

    关于name和password需要满足:

    $_GET['name'] != $_GET['password']
    sha1($_GET['name']) === sha1($_GET['password'])

    即name和password的值不等,但经过sha1加密之后的值相等

    这里我们也使用数组来进行绕过,因为sha1()函数不能处理数组类型,将报错并返回NULL,条件成立,输出flag

    最后的payload为:

    ?name[]=1&password[]=2
  • 相关阅读:
    BIOS详解:什么是BIOS ?BIOS的作用?CMOS及其与BIOS的关系?
    随机数不随机
    解决hexo神烦的DTraceProviderBindings MODULE_NOT_FOUND
    保护模式特权级别DPL,RPL,CPL 之间的联系和区别
    Linux内核 hlist_head/hlist_node结构解析
    x86中的页表结构和页表项格式
    Linux下/proc目录简介
    bdev文件系统
    X86 IO端口和MMIO
    Mac OS Alfred 2 tips
  • 原文地址:https://www.cnblogs.com/Cl0ud/p/13234475.html
Copyright © 2020-2023  润新知