Phar反序列化

Phar文件:PHAR(PHP归档文件时一种打包格式,通过将许多PHP代码文件和其他资源(例如图像,样式表等)捆绑刀一个归档文件中来实现应用程序和库的分发,所有PHAR文件都使用.phar作为文件拓展名,PHAR格式的归档需要使用自己些的PHP代码。

phar://协议:可以将多个文件归入一个本地文件夹,也可以包含一个文件

phar文件结构

a stub 识别phar拓展的表示

格式:xxx<?php xxx;_HALT_COMPLER();?>.对应的函数Phar::setStub

a manifest describing the contents 被压缩文件的权限、属性等信息.

这部分还会以序列化的形式存储用户自定义的meta-data,这是漏洞利用的核心部分。对应函数Phar:;setMetadata-设置phar归档元数据

the file contens 被压缩文件的内容

签名对应函数 Phar::stopBuffering-停止缓冲对Phar存档的写入请求

使用Phar类的前提

必须在php.ini中将phar.readonly配置项配置为0或Off,php中内置phar类,提供的部分操作如下:
a manifest describing the contetns ->phar 文件会以序列化的形式存储用户自定义的meta-data
Phar 为协议 -> 不依赖 unserialize()直接进行反序列化操作,在读取phar文件哩的数据时反序列化meta-data,就可以进行反序列化了

进行Phar反序列化(实例)

首先创建一个phar文件然后实例化Flag这个class然后使用setMetadata将类进行传入,这样我们就可以进行反序列化了
image.png
(ps:所有的文件函数都会导致phar反序列化)
接下来我们直接上例题

例题一(uuctf2022招新赛ez_phar)

如图
image.pngimage.png

image.png

例题二([SWPUCTF 2021 新生赛]babyunser)

image.png
image.png
image.png
题目一目了然很明显这里需要我们去通过文件查看器读取源码进行代码审计,我们分别读取index.php upload.php read.php 以及在read.php里面所包含的文件class.php

//upload.php
<?php
if (isset($_POST['submit'])) {
    $upload_path = "upload/" . md5(time()) . ".txt";
    $temp_file = $_FILES['upload_file']['tmp_name'];
    if (move_uploaded_file($temp_file, $upload_path)) {
        echo "文件路径:" . $upload_path;
    } else {
        $msg = '上传失败';
    }
}
?>

//read.php
<?php
error_reporting(0);
$filename = $_POST['file'];
if (!isset($filename)) {
    die();
}
$file = new zz($filename);
$contents = $file->getFile();
?>

//class.php
<?php
class aa{
    public $name;

    public function __construct(){
        $this->name='aa';
    }

    public function __destruct(){
        $this->name=strtolower($this->name);
    }
}

class ff{
    private $content;
    public $func;

    public function __construct(){
        $this->content="\<?php @eval(\$_POST[1]);?>";
    }

    public function __get($key){
        $this->$key->{$this->func}($_POST['cmd']);
    }
}

class zz{
    public $filename;
    public $content='surprise';

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

    public function filter(){
        if(preg_match('/^\/|php:|data|zip|\.\.\//i',$this->filename)){
            die('这不合理');
        }
    }

    public function write($var){
        $filename=$this->filename;
        $lt=$this->filename->$var;
        //此功能废弃,不想写了
    }

    public function getFile(){
        $this->filter();
        $contents=file_get_contents($this->filename);
        if(!empty($contents)){
            return $contents;
        }else{
            die("404 not found");
        }
    }

    public function __toString(){
        $this->{$_POST['method']}($_POST['var']);
        return $this->content;
    }
}

class xx{
    public $name;
    public $arg;

    public function __construct(){
        $this->name='eval';
        $this->arg='phpinfo();';
    }

    public function __call($name,$arg){
        $name($arg[0]);
    }
}

例题三(NSSCTF prize_p1)

例题四 [SUCTF 2019]Upload Labs 2

反序列化实战

命名空间中的反序列化漏洞

<?php
  namespace test\sub\level;

const test_const = 1;
class test_class{}
function test_func(){}

$a = new \tessub\level\test_class();

Thinkphp5.0、5.1、6.x反序列化漏洞分析

Laraval 5.8.x调用链分析

(未完)