php phar 文件使用,详解PHPphar协议对象注入技术,反序列化操作快速入门!

原标题:详解PHPphar协议对象注入技术,反序列化操作快速入门!

近日,在BlackHat 2018大会上公布了一种针对PHP应用程序的全新攻击技术。来自Secarma的安全研究员Sam Thomas分享了议题“It’s a PHP unserialization vulnerability Jim, but not as we know it”,利用phar文件会以序列化的形式存储用户自定义的meta-data这一特性,拓展了php反序列化漏洞的攻击面。

该方法在文件系统函数(file_exists()、is_dir()等)参数可控的情况下,配合phar://伪协议,可以不依赖unserialize()直接进行反序列化操作。

本期安仔课堂,ISEC实验室的老师为大家详解PHPphar协议对象注入技术。

fbb5142a81479f536644d45a6d25bbee.gif

0X00 PHP反序列化漏洞

PHP中有两个函数serialize()和unserialize()。

serialize():

当在PHP中创建了一个对象后,可以通过serialize()把这个对象转变成一个字符串,保存对象的值方便之后的传递与使用。

测试代码如下:

443ad5eb688b772ebc30cabf2a526a7a.png

图1

创建了一个新的对象,并且将其序列化后的结果打印出来:

8f74d3263360c26867e9cad4e42e0c09.png

图2

这里的O代表存储的是对象(object),假如传入的是一个数组,那就是字母a。6表示对象的名称有6个字符。“mytest“表示对象的名称。1表示有一个值。{s:4:"test";s:3:"123";}中,s表示字符串,4表示字符串的长度,“test”为字符串的名称,之后的类似。

unserialize():

与serialize()对应的,unserialize()可以对单一的已序列化的变量进行操作,将其转换回 PHP 的值。

e36bf4bef31052be570eed1257fc0676.png

图3

30a97999da4df2a0c681725e25ba55e2.png

图4

当使用unserialize()恢复对象时,将调用_wakeup()成员函数。

反序列化漏洞就是当传给unserialize()的参数可控时,可以通过传入一个精心构造的序列化字符串,来控制对象内部的变量甚至是函数。

0X01PHP伪协议

PHP带有很多内置URL风格的封装协议,可用于类似fopen()、copy()、file_exists()和fielsize()的文件系统函数。除了这些封装协议,还能通过stream_wrapper_register()来注册自定义的封装协议。

0X02phar文件结构和漏洞原理

phar文件有四部分构成:

1.a stub

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

2.a manifest describing the contents

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

da70cd8879d9c1eef0cf8c054789b7fa.png

图5

3.the file contents

被压缩文件的内容。

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

签名,放在文件末尾,目前支持的两种签名格式是MD5和SHA1。

3b93e17205ada7043c5cd576f7a832aa.png

图6

漏洞触发点在使用phar://协议读取文件的时候,文件内容会被解析成phar对象,然后phar对象内的meta-data会被反序列化。

meta-data是用serialize()生成并保存在phar文件中,当内核调用phar_parse_metadata()解析meta-data数据时,会调用php_var_unserialize()对其进行反序列化操作,因此会造成反序列化漏洞。

0X03漏洞利用和demo测试

Sam Thomas举例的漏洞主要通过利用魔术方法__destruct或__wakeup构造利用链,但是在实战环境里往往较难找到可以直接通过魔术方法触发的漏洞点。

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

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

335dc9ea19003070d3050c8981ab8739.png

图7

216ecc8b750a630620a13aee03995bf7.png

图8

可以明显的看到meta-data是以序列化的形式存储的:

f5e990040bad47515d47e82561c8eb71.png

图9

有序列化数据必然会有反序列化操作,PHP一大部分的文件系统函数在通过phar://伪协议解析phar文件时,都会将meta-data进行反序列化,测试后受影响的函数如下:

82b5e0aa55ff52dc16cfe2d7589d19e8.png

图10

php底层代码处理:

565fb2994971bb5bbb0954636ac0d489.png

图11

以下举例证明:

bebe261bf06f0c07a817b2f484ad5154.png

图12

118df47e00291e26f104c75e7a6da5dc.png

图13

对于其他的函数来说也是可行的:

f138c3dc48aac18d092fb62659d9046e.png

图14

在文件系统函数的参数可控时,可以在不调用unserialize()的情况下进行反序列化操作。

由于通过反序列化可以产生任意一种数据类型,可联想到PHP的一个漏洞:PHP内核哈希表碰撞攻击(CVE-2011-4885)。在PHP内核中,数组是以哈希表的方式实现的,攻击者可以通过巧妙构造数组元素的key使哈希表退化成单链表(时间复杂度从O(1)=>O(n))来触发拒绝服务攻击。

d80cc5e677f730cf323fe42a9e89f108.png

图15

PHP修复此漏洞的方式是限制通过$_GET或$_POST等方式传入的参数数量,但是如果PHP脚本通过json_decode()或unserialize()等方式获取参数,则依然将受到此漏洞的威胁。

漏洞利用思路:构造一串恶意的serialize数据(能够触发哈希表拒绝服务攻击),然后将其保存到phar文件的metadata数据区,当文件操作函数通过phar://协议对其进行操作的时候就会触发拒绝服务攻击漏洞。

通过如下代码生成一个恶意的phar文件:

bb7289954d5f4aefbc58e48112258998.png

图16

测试效果如下:

88ccfb5568ea021e9b970a15eb05740e.png

图17

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

PHP识别phar文件是通过文件头的stub,即__HALT_COMPILER();?>,对前面的内容或者后缀名没有要求。可以通过添加任意文件头加上修改后缀名的方式将phar文件伪装成其他格式的文件。

660aa9dfa06595cbec05f1863a9e8259.png

图18

6821480c156c10c27a79c7122b3af479.png

图19

5185c2f36a24d7759b58e787bf261c69.png

图20

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

0X05实际利用

利用条件:

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

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

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

利用环境:WordPress

WordPress是网络上最广泛使用的cms,这个漏洞在2017年2月份就被报告给了官方,但至今仍未被修补。之前的任意文件删除漏洞也是出现在这部分代码中,同样没有修补。根据利用条件,我们先要构造phar文件。

漏洞核心位于/wp-includes/post.php中的wp_get_attachment_thumb_file方法:

b9a16826c15b5510c9457c02af90fa2f.png

图21

可以通过XMLRPC调用wp.getMediaItem方法来实现此功能。

ddae277636520967f42e549d944f13b6.png

图22

如果$file是类似于Windows盘符的路径Z:\Z,正则匹配就会失败,$file就不会拼接其他东西,此时就可以保证basename($file)与$file相同。

寻找到能够执行任意代码的类方法:

0646721b48871b2e0daeffa8def9cba2.png

图23

这个类继承了ArrayIterator,每当这个类实例化的对象进入foreach被遍历的时候,current()方法就会被调用。

由于WordPress核心代码中没有合适的类能够利用,这里利用woocommerce插件中的一个类:

fd64b52a4629e8531d1b2f5b10594062.png

图24

由此构造完成pop链,构建出phar文件:

9c0ae31afd4aeb15cb60c812f26ca393.png

图25

065d80208584ffa3629f32562debd28b.png

图26

利用函数passthru来执行系统命令whoami。

这个漏洞利用的权限需要有作者权限或更高,这里用一个author。

22ad0a01bccbc7799c8b3797e9f5ab55.png

图27

通过xmlrpc接口上传刚才的文件,文件要用编码:

55c90d32e88bb85256403f9202ced508.png

图28

025404d7267f7068527c100226be440c.png

图29

获得_wponce值,可以在修改页面中获取:

da06b03abf3746245ef59dc4a55ee44c.png

图30

通过发送数据包来调用设置$file的值:

587ca9bba674b4596db84b22f2a10d46.png

图31

5b59fc360a92ce1c30f507baca922349.png

图32

139325582d14f3593ea19841d8461fab.png

图33

33bc1428003f070088baeea38be386fe.png

图34

最后通过XMLRPC调用wp.getMediaItem这个方法来调用wp_get_attachment_thumb_file()函数,从而触发反序列化。xml调用数据包如下:

23ef40b6f3259daacdb5f641e58688e1.png

图35

11c8463230bd9b16485718816548b894.png

图36

成功执行whoami。

0X06防御

1.在文件系统函数的参数可控时,对参数进行严格的过滤;

2.严格检查上传文件的内容,而不是只检查文件头;

3.在条件允许的情况下禁用可执行系统命令、代码的危险函数。返回搜狐,查看更多

责任编辑:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值