1. 漏洞原理:
1.1 描述
在Drupal Core版本7.62之前的7.x、8.6.6之前的8.6.x和8.5.9之前的8.5.x; 在不受信任的phar:// URI
上执行文件操作时,PHP的内置phar流包装器
中存在一个远程执行代码漏洞。某些Drupal代码(核心代码,贡献代码和自定义代码)可能会在未经充分验证的用户输入上执行文件操作,从而容易受到此漏洞的影响。但是此类代码路径通常需要访问管理权限或非典型配置,所以这个漏洞的影响不是太大。
1.2 Drupal
Drupal是使用PHP语言编写的开源内容管理框架(CMF),它由内容管理系统(CMS)和PHP开发框架(Framework)共同构成。
1.3 phar反序列化
phar提供了一种将整个PHP应用程序放入称为“ phar”(PHP存档)的单个文件中的方法,以便于分发和安装。
Phar文件结构主要包含三至四个部分:
A stub:可以理解为一个标志,格式为
xxx<?php xxx; __HALT_COMPILER();?>
,前面内容不限,但必须以__HALT_COMPILER();?>
来结尾,否则phar扩展将无法识别这个文件为phar文件。a manifest describing the contents:phar文件本质上是一种压缩文件,其中每个被压缩文件的权限、属性等信息都放在这部分。这部分还会以序列化的形式存储用户自定义的meta-data,这是phar反序列化的攻击手法最核心的地方。
the file contents
被压缩文件的内容。
a signature for verifying Phar integrity
1.4 漏洞触发流程
在Drupal的文件管理系统模块中,对文件目录的检查使用的时is_dir
函数,这是一个直接的文件操作函数,而在2018年的blackhat上有研究人员提出,如果对phar文件进行文件操作,则其中的meta-data数据则会反序列化执行。
而这个漏洞是在管理员登录的情况下上传一个经过phar化的图片文件作为头像,图片文件中包含恶意构造的Payload用来执行命令,然后在文件系统的配置页面下,修改临时目录的值指向这个图片文件(利用phar流访问的方式),服务端会对这个文件进行check看是不是一个目录:
同时就会对meta-data数据进行反序列化执行。
1.4 Payload数据构造
PoC中使用的是Drupal的两个关键类GuzzleHttp\HandlerStack
,GuzzleHttp\Psr7\FnStream
来进行构造的,阅读源码可以发现FnStream主要是实现一个自定义的方法,可以看到它的构造函数和析构函数是这样的:
会将传入的参数作为函数名创建,而每个函数名都是调用call_user_func
实现的,析构函数中判断是否存在_fn_close
方法,存在则调用。
而HandlerStack类则是通过将中间件堆叠在HTTP处理程序函数之上,创建组合的Guzzle处理程序函数,其成员private $handler
就是一个回调函数对象,可以进行已有函数的自定义来执行命令。
整理一下,调用栈大致如下:
- FnStream的析构函数通过
call_user_func(Array)
执行我们自定义的close
方法(里面实际是一个数组,由HandlerStack对象和”resolve”组成) - 然后就会去执行HandlerStack的resolve函数,而我们可以自定义HandlerStack的成员使它来执行系统命令
- 最后经过resolve解析后就会真正执行我们构造的函数(1.5的EXP中是
passthru("uname -a")
)了。
1.5 可执行任意的命令的Exp
用PHP写的,php语法不是太熟,还请见谅:
1 |
|
1.6 PHP 执行系统命令的函数
system()
输出并返回最后一行shell结果。exec()
不输出结果,返回最后一行shell结果,所有结果可以保存到一个返回的数组里面。passthru()
只调用命令,把命令的运行结果原样地直接输出到标准输出设备上。
2. 复现过程:
2.1 环境搭建
使用vulhub现有的漏洞镜像来搭建环境,在服务器上安装docker和docker-compose,使用git克隆vulhub仓库到服务器,进入CVE-2019-6339的目录,使用docke-compose编译、启动环境:
1 | curl -s https://get.docker.com/ | sh |
目录下的docker-compose.yml中设置的端口是8080,因为是在公网的服务器嘛,我稍微改了一下。
然后在浏览器访问ip:port
就能看见drupal的安装界面了,一路配置下去,注册管理员,成功进入管理员的信息配置页面之后我们就可以上传我们通过EXP生成的头像文件了。
2.2 exp生成
由于上传有文件格式验证,所以我们在phar的头部加了个GIF的头,生成的整个exp如下:
2.3 执行过程
修改生成的poc1.phar文件名为test6.gif,上传:
然后访问admin/config/media/file-system
,修改临时目录为phar://./sites/default/files/pictures/2020-11/test6.gif
,保存设置,页面上返回了”uname -a”执行后的结果:
由于这是一个只有管理员才能访问的页面,因此这个漏洞虽然评分很高,但是影响有所减小。
参考链接:
- http://www.y1nhui.com/2019/12/07/cve-2019-6339%E5%A4%8D%E7%8E%B0/
- https://cloud.tencent.com/developer/article/1355389
- https://nvd.nist.gov/vuln/detail/CVE-2019-6339
- https://www.toolnb.com/tools/phpserialize.html
- https://paper.seebug.org/680/
- https://www.cnblogs.com/Byqiyou/p/10187672.html
- https://i.blackhat.com/us-18/Thu-August-9/us-18-Thomas-Its-A-PHP-Unserialization-Vulnerability-Jim-But-Not-As-We-Know-It-wp.pdf