[GFCTF 2021]Baby_Web

[GFCTF 2021]Baby_Web

一道cve和php代码审计的题目,进入题目发现没什么东西,

看网页源码

发现一个xxx.php.txt文件,这道题也是一道cve路径穿越漏洞

直接上网搜payload

/cgi-bin/.%2e/.%2e/.%2e/.%2e

接下来直接目录遍历,题目中说是上层目录,那就是html目录,问我怎么知道,猜的。根据题目的描述,我猜应该是在www.php.txt中,这次我猜错了,猜了几次才猜到是index.php.txt,index是五个字母啊

得到源码

发现里面有Class.php文件我们利用刚才的那种形式接着读

<?php
defined('main') or die("no!!");
Class Temp{
    private $date=['version'=>'1.0','img'=>'https://www.apache.org/img/asf-estd-1999-logo.jpg'];
    private $template;
    public function __construct($data){

$this->date = array_merge($this->date,$data);
}
public function getTempName($template,$dir){
    if($dir === 'admin'){
        $this->template = str_replace('..','','./template/admin/'.$template);
        if(!is_file($this->template)){
            die("no!!");
        }
    }
    else{
        $this->template = './template/index.html';
    }
}
public function display($template,$space=''){

    extract($this->date);
    $this->getTempName($template,$space);
    include($this->template);
}
public function listdata($_params){
    $system = [
        'db' => '',
        'app' => '',
        'num' => '',
        'sum' => '',
        'form' => '',
        'page' => '',
        'site' => '',
        'flag' => '',
        'not_flag' => '',
        'show_flag' => '',
        'more' => '',
        'catid' => '',
        'field' => '',
        'order' => '',
        'space' => '',
        'table' => '',
        'table_site' => '',
        'total' => '',
        'join' => '',
        'on' => '',
        'action' => '',
        'return' => '',
        'sbpage' => '',
        'module' => '',
        'urlrule' => '',
        'pagesize' => '',
        'pagefile' => '',
    ];

    $param = $where = [];

    $_params = trim($_params);

    $params = explode(' ', $_params);
    if (in_array($params[0], ['list','function'])) {
        $params[0] = 'action='.$params[0];
    }
    foreach ($params as $t) {
        $var = substr($t, 0, strpos($t, '='));
        $val = substr($t, strpos($t, '=') + 1);
        if (!$var) {
            continue;
        }
        if (isset($system[$var])) { 
            $system[$var] = $val;
        } else {
            $param[$var] = $val; 
        }
    }
    // action
    switch ($system['action']) {

        case 'function':

            if (!isset($param['name'])) {
                return  'hacker!!';
            } elseif (!function_exists($param['name'])) {
                return 'hacker!!';
            }

            $force = $param['force'];
            if (!$force) {
                $p = [];
                foreach ($param as $var => $t) {
                    if (strpos($var, 'param') === 0) {
                        $n = intval(substr($var, 5));
                        $p[$n] = $t;
                    }
                }
                if ($p) {

                    $rt = call_user_func_array($param['name'], $p);
                } else {
                    $rt = call_user_func($param['name']);
                }
                return $rt;
            }else{
                return null;
            }
        case 'list':
            return json_encode($this->date);
    }
    return null;
}

给了个/template/admin/我们访问一下

说明它最后会调用listdata,而在list方法中存在着危险函数

$rt = call_user_func_array($param['name'], $p);
                } else {
                    $rt = call_user_func($param['name']);
                }

这就是我们所要利用的点了,利用变量覆盖执行回调函数,虽然我们还不知道可以用什么函数,我们可以先传一个phpinfo;

首先,我们需要包含index.html文件,为mod传值,action的值就是function,因为case的值只有是这一种情况时才能去调用call_user_func函数,所以filename=index.html;而进入template/admin/index.html这个页面还需要让dir=admin,所以就是让space=admin,但space上文定义为空所以我们需要变量覆盖来让space=admin,但最后调用listdata方法,我们还需要为变量$mod传值,这个值是多少无所谓,最后进入call_user_func危险函数,传值是键值为name的变量值成功执行phpinfo,大致就是这个思路,传值时注意源码中数组的定义是以空格分割开的

所以最后的payload为

?filename=index.html

space=admin&mod=wda action=function name=phpinfo

最后得到flag

posted @ 2022-08-07 21:12  Delint  阅读(74)  评论(0)    收藏  举报