0x00 预备知识
什么是序列化
- 序列化 (serialize)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。【将状态信息保存为字符串】
- 简单的理解:将PHP中 对象、类、数组、变量、匿名函数等,转化为字符串,方便保存到数据库或者文件中
- 当在php中创建了一个对象后,可以通过serialize()把这个对象转变成一个字符串,保存对象的值方便之后的传递与使用。
什么是反序列化
- 序列化就是将对象的状态信息转为字符串储存起来,那么反序列化就是再将这个状态信息拿出来使用。(重新再转化为对象或者其他的)【将字符串转化为状态信息】
- 与 serialize() 对应的,unserialize()可以从已存储的表示中创建PHP的值
反序列化漏洞
- 本质上serialize()和unserialize()在PHP内部实现上是没有漏洞的,漏洞的主要产生是由于应用程序在处理对象、魔术函数以及序列化相关问题的时候导致的。
- 当传给 unserialize() 的参数可控时,那么用户就可以注入精心构造的payload。当进行反序列化的时候就有可能会触发对象中的一些魔术方法,造成意想不到的危害。
魔术方法
php中有一类特殊的方法叫“Magic function”(魔术方法), 这里我们着重关注一下几个:
- __construct():当对象创建(new)时会自动调用。但在unserialize()时是不会自动调用的。(构造函数)
- __destruct():当对象被销毁时会自动调用。(析构函数)
- __wakeup():如前所提,unserialize()时会自动调用。
- __toString():方法用于一个类被当成字符串时应怎样回应。例如 echo $obj;应该显示些什么。
0x01 环境搭建
漏洞环境:https://vulhub.org/#/environments/phpmyadmin/WooYun-2016-199433/
启动环境
sudo docker-compose up
- 1
查看当前运行漏洞环境
sudo docker ps
- 1
本地访问没问题,环境搭建成功(因为没有连接到数据库,我们将得到一个错误。但此漏洞与数据库无关,因此请忽略)
0x02 影响范围
phpmyadmin 2.8.0.3
0x03 漏洞成因
通过 exec 命令对指定的容器执行 bash然后查看源码:
sudo docker exec -it 53b9559d9612 /bin/bash
- 1
也可以下载到本地查看,更方便:
sudo docker cp 53b9559d9612:/var/www/html/libraries /home/vulhub/pma
- 1
查看存在漏洞的文件代码 /scripts/setup.php
发现当configuration传参存在且action传参不为’clear’时,将传入的connfiguration给反序列化;而setup.php中又引入了common.lib.php,接下来查看common.lib.php:
common.lib.php中又引入了Config.class.php,接下来看Config.class.php:
Config.class.php中含有__wakeup()魔术方法,因此可以构造序列化参数,其中又调用了load()方法,接下来继续看load方法:
整体思路就是:
setup.php -> common.lib.php -> Config.class.php -> __wakeup() -> load() -> eval();
- 1
0x04 漏洞复现
构造payload修改source的值后得到的序列化值作为configuration的传参,就可以输出任意文件内容
poc:
configuration=O:10:"PMA_Config":1:{s:6:"source",s:11:"/etc/passwd";}&action=test
- 1
注意需要满足两个条件:1. POST请求方法;2. action的传参不为clear:
复现结束后别忘了关闭docker容器:
docker-compose down
- 1
经过分析这个漏洞是不能读取php文件的,而因为又了eval()函数,相当于任意文件包含了。getshell需要包含上传的木马文件,也可以包含日志。但docker环境中并未开启日志功能,也没有上传点,因此getshell比较困难。
在Ubuntu下一般不允许root权限运行,无法读取access.log。在windows下几乎所有浏览器和python模块都会将特殊字符编码进行转换,getshell就更困难了,只能用socket去构造shell,参考下面这篇文章:
https://docs.ioin.in/writeup/www.mottoin.com/4cb63e7c-9151-42da-a5bd-e6e29e7ff2f8/index.html(pma任意文件包含导致代码执行)
参考链接:
https://docs.ioin.in/writeup/www.mottoin.com/4cb63e7c-9151-42da-a5bd-e6e29e7ff2f8/index.html(pma任意文件包含导致代码执行)
https://www.cnblogs.com/ichunqiu/p/10484832.html(PHP反序列化漏洞利用总结)