php phar 混淆,深入理解PHP Phar反序列化漏洞原理及利用方法(一)

Phar反序列化漏洞是一种较新的攻击向量,用于针对面向对象的PHP应用程序执行代码重用攻击,该攻击方式在Black Hat 2018会议上由安全研究员Sam Thomas公开披露。类似于对编译二进制文件的ROP(Return-oriented Programming)攻击,这种类型的漏洞利用PHP对象注入(POI),这是面向对象的PHP代码上下文中的一种面向属性的编程(POP)。

由于其新颖性,这种攻击媒介在过去的几个月中越来越受到安全届的关注,导致在许多广泛部署的平台中,接连发现远程代码执行漏洞,例如:

· Wordpress < 5.0.1 (CVE-2018-20148)

· Drupal 8.6.x, 8.5.x, 7.x  (CVE-2019-6339)

· Prestashop 1.6.x, 1.7.x (CVE-2018-19126)

· TCPDF < 6.2.19 (CVE-2018-17057)

· PhpBB 3.2.3 (CVE-2018-19274)

在本系列文章中,我们的主要目的是讲解Phar反序列化漏洞的内部工作原理,并进行实战操作,尝试利用PhpBB 3.2.3版本平台中的远程代码执行漏洞。

c018af3302c219d9b2adc7d39bc9b2a7.png 关于Phar文件、DESERIALIATION和PHP包装器

为了更好地理解这个攻击向量是如何工作的,我们首先需要了解Phar文件是什么、反序列化攻击的原理、PHP包装器是什么,以及上述三个概念是如何关联的。

c018af3302c219d9b2adc7d39bc9b2a7.png 什么是Phar文件?

Phar(PHP Archive)文件是一种使用单一文件格式分发PHP应用程序和库的方法(类似于JAR文件在Java生态系统中的工作方式。这些Phar文件也可以直接包含在我们自己的PHP代码中。在结构上,它们只是用于压缩,具有可选gzip压缩或基于ZIP压缩文件的tar文件),PHP文档中描述的具体细节如下:

1. 存根(Stub):当Phar作为独立应用程序运行时,它是一个PHP代码序列,充当引导程序。其中,至少必须包含以下代码:

2. 描述存档中包含的源文件的清单:该文件属于可选,保存序列化的元数据,这一序列化的块是漏洞利用链中的关键一环,后续我们将详细说明。

3. 源文件:实际的Phar功能。

4. 一种可选签名,用于完整性检查。

c018af3302c219d9b2adc7d39bc9b2a7.png 了解反序列化漏洞

序列化是指以二进制格式存储对象属性的过程,以允许其传递或存储在磁盘上,因此可以在以后对其进行反序列化和使用。

在PHP中,序列化过程仅会保存对象的属性、类名,但不保存其方法(因此其缩写词是POP)。从安全的角度来看,这被证明是一种明智的设计方案,除了有一个使反序列化过程变得危险的“魔术方法”。

这些函数特定于每个PHP类,具有Double-underscore的前缀名称,并在某些运行时事件上隐式调用。默认情况下,大多数时间什么都不做,开发人员的工作就是定义它们的行为。在我们的实际案例中,有以下两项值得特别关注,因为它们是只能被Phar反序列化触发的因素:

1. __wakeup():在对象的反序列化过程中调用实现;

2. __destruct():在代码中不再适用对象并被垃圾收集器销毁时隐式调用。

接下来,我们具体来看看如何使用此向量,在虚拟的示例中利用易受攻击的代码片段:

# file: dummy_class.php

/* Let's suppose some serialized data is written on the disk with

loose file permissions and gets read at a later time */

class Data {

# Some default data

public $data = array("theme"=>"light", "font"=>12);

public $wake_func = "print_r";

public $wake_args = "The data has been read!\n";

# magic method that is called on deserialization

public function __wakeup() {

call_user_func($this->wake_func, $this->wake_args);

}

}

# acting as main the conditional below gets executed only when file is called directly

if (basename($argv[0]) == basename(__FILE__)) {

# Serialize the object and dump it to the disk; also free memory

$data_obj = new Data();

$fpath = "/tmp/777_file";

file_put_contents($fpath, serialize($data_obj));

echo "The data has been written.\n";

unset($data_obj);

# Wait for 60 seconds, then retrieve it

echo "(sleeping for 60 seconds…)\n";

sleep(60);

$new_obj = unserialize(file_get_contents($fpath));

}

我们注意到,在反序列化时,__wake方法动态调用对象的$wake_func和$wake_args属性指向的print_r函数。经过简单的运行后,产生以下输出:

$ php dummy_class.php

The data has been written.

(sleeping for 60 seconds…)

The data has been read!

但是,如果在60秒的时间内,我们设法是用自己的序列化数据替换原序列化数据,从而控制反序列化中所要求的的函数呢?下面的代码描述了如何完成此操作:

# file: exploit.php

require('dummy_class.php');

# Using the existing class definition, we create a crafted object and overwrite the

# existing serialized data with our own

$bad_obj = new Data();

$bad_obj->wake_func = "passthru";

$bad_obj->wake_args = "id";

$fpath = "/tmp/777_file";

file_put_contents($fpath, serialize($bad_obj));

尽管dummy_class.php的源代码没有改变,但是当dummy_class.php正在等待的过程中,如果在60秒的时间内运行上面的代码片段,我们就能够得到一个完美的代码执行。该行为是由序列化对象的动态函数调用产生的,通过对象的属性更改为passthru("id")。

$ php dummy_class.php

The data has been written.

(sleeping for 60 seconds…)

uid=33(www-data) gid=33(www-data) groups=33(www-data),1001(nagios),1002(nagcmd)

在PHP对象注入(POI/反序列化)攻击的上下文中,这些易受攻击的代码序列中包含Gadget或POP链的名称。

c018af3302c219d9b2adc7d39bc9b2a7.png PHP包装器:将它们包装在一起

根据PHP文档上的描述,流(Stream)是与文件、网络、数据压缩以及共享一组通用功能和用途的其他操作相关的方式。PHP包装器负责执行处理各种协议的复杂任务,并提供带有协议数据的流接口。这些流通常由文件系统函数使用,例如:fopen()、copy()和filesize()。

使用类似URL的语法方案访问流wrapper://source。PHP提供的最常见流接口是:

· file:// - 访问本地文件系统

· http:// - 访问HTTP(s) URL

· ftp:// - 访问FTP(s) URL

· php:// - 访问多种I/O流

我们需要重点关注的一种流类型是(*drum roll*) phar://包装器。其典型的格式类似于phar://full/or/relative/path,并且包含两个值得关注的属性:

1. 在声明流时,不会检查其文件扩展名,从而使phar文件成为名副其实的多类型候选者。

2. 如果使用phar流作为参数调用文件系统函数,那么Phar的序列化元数据会自动通过设计实现反序列化。

下面是触发Phar反序列化的文件系统函数列表:

copy                file_exists         file_get_contents   file_put_contents  file                fileatime           filectime           filegroup          fileinode           filemtime           fileowner           fileperms          filesize            filetype            fopen               is_dir             is_executable       is_file             is_link             is_readable        is_writable         lstat               mkdir               parse_ini_file     readfile            rename              rmdir               stat                touch               unlink

1bc17a8d5364fd914569e08a1e947bbf.png如何进行Phar反序列化攻击

至此,我们已经拥有了漏洞利用所需的所有组成部分。利用Phar反序列化漏洞所需的条件通常包括:

1. 应用程序源代码(包括第三方库)中存在小工具/弹出链,允许POI利用;大多数情况下,这都是通过检查源代码来发现的。

2. 能够包含本地或远程恶意Phar文件(最常见的一种是,通过文件上传和依赖于多类型(Polyglot))。

3. 在用户控制的Phar包装器上调用文件系统函数的入口点,也可以通过检查源代码发现。

在本博客文章的第二部分,我们将通过在PhpBB 3.2.3(CVE-2018-19274)中利用远程代码执行漏洞,来具体理解这些概念是如何应用的。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值