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

本期安仔教室,ISEC实验室的老师为大家详解PHPphar协议工具注入技能。

0X00 PHP反序列化漏洞

phpphar扩展详解PHPphar协定对象注入技巧反序列化操作快速入门 GraphQL

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

serialize():

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

测试代码如下:

图1

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

图2

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

unserialize():

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

图3

图4

当利用unserialize()规复工具时,将调用_wakeup()成员函数。

反序列化漏洞便是当传给unserialize()的参数可控时,可以通过传入一个精心布局的序列化字符串,来掌握工具内部的变量乃至是函数。

0X01PHP伪协议

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

0X02phar文件构造和漏洞事理

phar文件有四部分构成:

1.a stub

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

2.a manifest describing the contents

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

图5

3.the file contents

被压缩文件的内容。

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

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

图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文件。

图7

图8

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

图9

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

图10

php底层代码处理:

图11

以下举例证明:

图12

图13

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

图14

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

由于通过反序列化可以产生任意一种数据类型,可遐想到PHP的一个漏洞:PHP内核哈希表碰撞攻击(CVE-2011-4885)。
在PHP内核中,数组因此哈希表的办法实现的,攻击者可以通过奥妙布局数组元素的key使哈希表退化成单链表(韶光繁芜度从O(1)=>O(n))来触发谢绝做事攻击。

图15

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

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

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

图16

测试效果如下:

图17

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

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

图18

图19

图20

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

0X05实际利用

利用条件:

1.phar文件要能够上传到做事器端。

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

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

利用环境:WordPress

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

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

图21

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

图22

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

探求到能够实行任意代码的类方法:

图23

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

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

图24

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

图25

图26

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

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

图27

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

图28

图29

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

图30

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

图31

图32

图33

图34

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

图35

图36

成功实行whoami。

0X06防御

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

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

3.在条件许可的情形下禁用可实行系统命令、代码的危险函数。