phar

phar扩展提供了一种将整个php应用程序放入名为“phar”(php archive)的单个文件中的方法,以便于分发和安装。除了提供这个服务之外,phar扩展还提供了一个文件格式抽象方法,用于通过phardata类创建和操作tar和zip文件,就像pdo为访问不同的数据库提供了一个统一的接口一样。与pdo不同,pdo不能在不同的数据库之间进行转换,phar还可以用一行代码在tar、zip和phar文件格式之间进行转换。

什么是Phar?phar归档是将多个文件组合成一个文件的一种方便方法。因此,phar归档提供了一种方法,可以在单个文件中分发完整的php应用程序,并从该文件运行它,而无需将其提取到磁盘。此外,phar档案可以像任何其他文件一样在命令行和web服务器上由php轻松执行。phar有点像php应用程序的拇指驱动器。

phar通过流包装器实现此功能。通常,要在php脚本中使用外部文件,可以使用include。

反序列化

通常,我们见到的反序列化都是通过将序列化后的字符串传入unserialize()函数中,进行反序列化执行代码。而phar拓展可以在不使用php函数unserialize()的前提下,引起严重的php对象注入漏洞。利用phar文件会以序列化的形式存储用户自定义的meta-data这一特性,拓展了php反序列化漏洞的攻击面。该方法在文件系统函数file_exists()、is_dir()等)参数可控的情况下,配合phar://伪协议,可以不依赖unserialize()直接进行反序列化操作。

关于流包装

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

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

phar拓展

所有Phar文件包含三到四个部分

Phar file stub

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

a manifest describing the contents

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

the file contents

被压缩文件的内容。

[optional] a signature for verifying Phar integrity (phar file format only)

签名,放在文件末尾,包含签名的phar总是在加载程序、清单和文件内容之后将签名附加到phar存档的末尾。此时支持的两种签名格式是md5和sha1。
uqfMjS.png

测试

根据文件结构我们来自己构建一个phar文件,php内置了一个Phar类来处理相关操作。
注意:要将php.ini中的phar.readonly选项设置为Off,否则无法生成phar文件。
新建alex.php

<?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("alex.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>

浏览器访问alex.php,自动在当前目录下生成phar.phar。
用winhex打开:
uqhtVH.png
可以明显的看到meta-data是以序列化的形式存储的。
有序列化数据必然会有反序列化操作,php一大部分的文件系统函数在通过phar://伪协议解析phar文件时,都会将meta-data进行反序列化,测试后受影响的函数如下:
uqhqo9.png

实例:
alex.php:

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

phar1.php:

<?php
class TestObject{
    function __destruct()
    {
        echo $this->name;
    }
}
include('phar://phar.phar/alex.txt');

先生成phar.phar后,访问phar1.php得到:testalex
当文件系统函数的参数可控时,我们可以在不调用unserialize()的情况下进行反序列化操作,一些之前看起来“人畜无害”的函数也变得“暗藏杀机”,极大的拓展了攻击面。

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

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

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

采用这种方法可以绕过很大一部分上传检测。

实际利用

利用条件

  1. phar文件要能够上传到服务器端。
  2. 要有可用的魔术方法作为“跳板”。
  3. 文件操作函数的参数可控,且:/phar等特殊字符没有被过滤。

    利用方法

    师傅说的很详细,我就不说了。。。
    参考:漏洞验证

防御

  1. 在文件系统函数的参数可控时,对参数进行严格的过滤。
  2. 严格检查上传文件的内容,而不是只检查文件头。
  3. 在条件允许的情况下禁用可执行系统命令、代码的危险函数。

参考:

利用 phar 拓展 php 反序列化漏洞攻击面
初探phar://

  • linux三剑客

    前言之前用一些脚本都经常用到grep,sed,awk。但是一直不太熟悉,今天来学习一下,做个备忘录。 grep格式: grep [OPTIONS] PATTERN [FILE...] grep [OPTIONS] [-e PATTER...

    linux三剑客
  • i春秋2020新春战“疫”网络安全公益赛 web Writeup

    前言这次比赛题目质量挺好的,除啦环境可能有时候有点问题。(就让我遇到了。心态炸了一天。。。)其他都挺好的。 DAY1简单的招聘系统知识点:sql注入的联合注入或盲注存在注册和登陆功能,首先进行注册后登陆进系统,发现有一个模块是管理员才...

    i春秋2020新春战“疫”网络安全公益赛 web Writeup
  • 计算机组成原理学习

    计算机组成原理第一章 计算机系统概论计算机系统的层次结构 冯·诺依曼计算机的特点 计算机由运算器、存储器、控制器、输入设备和输出设备五大部件组成 指令(程序)和数据以二进制同等地位地存储在存储器中,可按址寻访 指令由操作码和地址码组...

    计算机组成原理学习
  • 2019安洵杯+2019广外比赛web部分题解

    2019安洵杯easy_web知识点:MD5强碰撞,命令执行这个题比较简单,看题目发现传入参数img和cmd,然而图片是传入的img参数控制,让我想到ddctf的一道题,然后发现img是通过把文件名进行转十六进制后两次base64编码...

    2019安洵杯+2019广外比赛web部分题解
  • bypass disfunction

    前言PHP 的 disabled_functions主要是用于禁用一些危险的函数防止攻击者执行系统命令。但是有一些绕过方法。这里做个总结。 基本思路有四种绕过 disable_functions 的手法:第一种,攻击后端组件,寻找存在...

    bypass disfunction
  • 2019极客大挑战RCE ME

    题目环境:http://114.116.44.23:40001/ 题目还是老样子。无字母数字rce。知识点其实都有写过,就不说了。详细参见:【RCE提高篇】题目源码: <?php ini_set("display_errors"...

    2019极客大挑战RCE ME
  • RCE提高篇

    前言首先,需要了解一下命令执行的函数,这里推荐几篇文章,来认识这些函数。浅谈eval和assert从底层分析eval和assert的区别命令执行与代码执行的小结巧用命令注入的N种方式命令注入绕过姿势我就不在说这几个东西,大牛们都说的很...

    RCE提高篇
  • buuctf刷题记录(序)

    love math知识点:代码审计,绕waf直接给出源码: <?php error_reporting(0); //听说你很喜欢数学,不知道你是否爱它胜过爱flag if(!isset($_GET['c'])){ sho...

    buuctf刷题记录(序)
  • 基本工具使用

    常用工具nc/ncatnc被誉为网络界的瑞士军刀。它的功能可见一般。。。 侦听模式 / 传输模式 telnet / 获取banner信息 传输文本信息 传输文件/传输目录 加密传输文件 远程控制/木⻢ 加密所有流量 流...

    基本工具使用
  • buuctf刷题记录

    前言最近感觉自己菜出来新境界。。。刷点题来证明我还存在。。。言归正传。开刷 hack world知识点:sql布尔盲注,bypass进入题目,发现这是典型的sql布尔盲注,题目给出了表名和列名都是flag,用burp进行fuzz测试发...

    buuctf刷题记录