phpMyAdmin文件包含漏洞(CVE-2018-12613)

phpMyAdmin文件包含漏洞 #

phpMyAdmin简介 #

什么是phpMyAdmin #

phpMyAdmin是一个基于网页的 MySQL / MariaDB 数据库可视化管理工具,使用PHP编写。phpMyAdmin最大的作用就是让我们不用敲复杂的命令行也能轻松管理数据库。它提供一个直观的图形界面,所有操作都可以在浏览器点击鼠标完成。

phpMyAdmin能干什么 #

它的功能几乎覆盖数据库管理的所有方面:

  • 基本操作:创建、浏览、编辑、删除数据库、数据表、字段和索引。
  • 执行 SQL 语句、通过表单搜索数据、批量导入导出数据(支持 CSV、SQL、XML、PDF 等多种格式)。
  • 权限与维护:管理 MySQL 用户账号和权限,检查和修复数据表,追踪数据库变更。
  • 其他高级功能:支持创建数据库关系图(PDF)、管理存储过程和触发器、支持 80 多种语言等。

CVE-2018-12613 #

漏洞分析 #

在index.php中出现问题:

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不能在黑名单中,也就是import.php和export.php。

第五条Core::checkPageValidity()方法在libraries\classes\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;
    }

验证的白名单为:

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进行URL解码,然后截取第一次出现的“?”前面的内容,如果这一段内容在白名单中,即可文件包含。

利用手法 #

由于PHP的include函数在包含文件的时候文件名里面出现“?”这种字符会被当做文件名,我们在“?”后面进行目录遍历即可。

例如:

target=db_datadict.php%253f/../../../../../../../../etc/passwd

Getshell #

由于phpMyAdmin是可以直接控制数据库的,因此如果我们直接把webshell写入数据库,然后包含这个数据库文件就可以实现getshell。