phpMyAdmin本地文件包含漏洞

4 phpMyAdmin本地文件包含漏洞

4.1 摘要

4.1.1 漏洞簡介

  • phpMyAdmin是一個web端通用MySQL管理工具,上述版本在/libraries/gis/pma_gis_factory.php文件裏的存在任意文件包含漏洞,攻擊者利用此漏洞能夠獲取數據庫中敏感信息,存在GETSHELL風險。

4.1.2 漏洞環境

  • Windows XP
  • php 5.2.17
  • phpMyAdmin 4.0.1--4.2.12

4.2 漏洞復現

4.2.1 構造木馬

  • 在網站根目錄放置phpinfo.txt(包含phpinfo())包含一句話木馬等操做,上傳後達到GETSEHLL的目的。該文件內PHP代碼能夠打印出PHP詳細的版本等信息,用來測試任意文件包含。

4.2.2 構造URL直接訪問

  • 打開http://localhost/頁面來訪問本地搭建的存在漏洞的phpMyAdmin,建立一個普通用戶root,密碼root,沒有任何權限,登陸後只能看到test、mysql、information_schema表:

  • 竟然一片空白,沒有出現我想要的phpinfo!?
  • 這又涉及到phpmyadmin的一個防護CSRF機制了,來到libraries/common.inc.php ,代碼以下:
$token_mismatch = true;
if (PMA_isValid($_REQUEST['token'])) {
    $token_mismatch = ($_SESSION[' PMA_token '] != $_REQUEST['token']);
}
//檢查$_SESSION[‘ PMA_token ‘] 是否等於 $_REQUEST[‘token’]
if ($token_mismatch) {//若是不等於
    /**
     *  不安全源容許的參數列表
     */
    $allow_list = array(
        /* 直接訪問所需,參見常見問題1.34
         * 此外,服務器須要cookie登陸屏幕(多服務器)
         */
        'server', 'db', 'table', 'target', 'lang',
        /* Session ID */
        'phpMyAdmin',
        /* Cookie preferences */
        'pma_lang', 'pma_collation_connection',
        /* Possible login form */
        'pma_servername', 'pma_username', 'pma_password',
        /* Needed to send the correct reply */
        'ajax_request',
        /* Permit to log out even if there is a token mismatch */
        'old_usr'
    );
    /**
     * 容許在 test/theme.php中更改主題
     */
    if (defined('PMA_TEST_THEME')) {
        $allow_list[] = 'set_theme';
    }
    /**
     * Require cleanup functions
     */
    include './libraries/cleanup.lib.php';
    /**
     * Do actual cleanup
     */
    PMA_remove_request_vars($allow_list);//進入PMA_remove_request_vars函數
}
  • 上面代碼檢查了$_SESSION[‘ PMA_token ‘]是否等於 $_REQUEST[‘token’],若是不等於,最後會進入PMA_remove_request_vars函數,代碼以下:
function PMA_remove_request_vars(&$whitelist)
{
    /* 
     * 不要只檢查$_REQUEST由於它可能已被覆蓋
     * 並使用類型轉換,由於變量可能已經成爲字符串
     */
    $keys = array_keys(
        array_merge((array)$_REQUEST, (array)$_GET, (array)$_POST, (array)$_COOKIE)
    );
    foreach ($keys as $key) {
        if (! in_array($key, $whitelist)) {
            unset($_REQUEST[$key], $_GET[$key], $_POST[$key], $GLOBALS[$key]);
        } else {
            // allowed stuff could be compromised so escape it
            // we require it to be a string
            if (isset($_REQUEST[$key]) && ! is_string($_REQUEST[$key])) {
                unset($_REQUEST[$key]);
            }
            if (isset($_POST[$key]) && ! is_string($_POST[$key])) {
                unset($_POST[$key]);
            }
            if (isset($_COOKIE[$key]) && ! is_string($_COOKIE[$key])) {
                unset($_COOKIE[$key]);
            }
            if (isset($_GET[$key]) && ! is_string($_GET[$key])) {
                unset($_GET[$key]);
            }
        }
    }
}
  • 全部的$_REQUEST $_POST $_COOKIE $_GET都清空了,那麼後面的操做確定不能正常運轉了。因此,必須帶上token訪問。

4.2.3 獲取token

  • 使用phpmyadmin時,注意到通常在訪問pma的時候都會在url裏看到token=xxx這個參數,點擊hackbar工具的load url便可將url地址加載到hackbar的欄目中,把該token複製下來,準備下一步操做利用任意文件包含。
  • 在hackbar欄目中輸入http://localhost/gis_data_editor.php?token=(上面操做複製的內容粘貼進入這裏)&gis_data[gis_type]=/../../../phpinfo.txt%00輸入完畢後點擊Execute提交便可,便可包含執行phpinfo.txt中的php代碼, 以下圖所示:
  • 打印出PHP詳細的版本等信息,漏洞利用成功。

4.3 漏洞分析

  • 分析官方發佈的漏洞補丁,libraries/gis/pma_gis_factory.php代碼以下:
public static function factory($type)    {
        include_once './libraries/gis/pma_gis_geometry.php';
               $type_lower = strtolower($type);
               if (! file_exists('./libraries/gis/pma_gis_' . $type_lower . '.php')) {
                     if(! PMA_isValid($type_lower, PMA_Util: :getGISDatatypes())
                        || ! file_exits(' ./libraries/gis/pma_gis' . $type_lower . '.php)//file_exists判斷文件是否存在
                      ){
                           return false;
                       }
               if (include_once './libraries/gis/pma_gis_' . $type_lower . '.php') {//include_once包含這個文件
  • 對比下有漏洞的/libraries/gis/pma_gis_factory.php代碼:
public static function factory($type)    {
        include_once './libraries/gis/pma_gis_geometry.php';
               $type_lower = strtolower($type);
               if (! file_exists('./libraries/gis/pma_gis_' . $type_lower . '.php')) {
                   return false;
               }
               if (include_once './libraries/gis/pma_gis_' . $type_lower . '.php') {
  • 能夠看到多了一段 PMA_isValid($type_lower, PMA_Util::getGISDatatypes())$type_lower參數的判斷,大概能夠猜想漏洞和這個參數有關係。
  • 這裏的代碼邏輯是:用file_exists判斷文件是否存在,若是存在,就用include_once包含這個文件。若是$type_lower這個變量是可控的,那麼就形成文件包含漏洞。追溯$type_lower的來源,能夠發現是factory函數的參數,因此找調用factory函數的地方gis_data_editor.php
1     // Get data if any posted
2     $gis_data = array();
3     if (PMA_isValid($_REQUEST['gis_data'], 'array')) {
4         $gis_data = $_REQUEST['gis_data'];//獲取到gis_data參數的值
5     }
6     $gis_types = array(
7         'POINT',
8         'MULTIPOINT',
9         'LINESTRING',
10       'MULTILINESTRING',
11       'POLYGON',
12       'MULTIPOLYGON',
13       'GEOMETRYCOLLECTION'
14   );
15   // 從初始調用中提取類型並確保它是有效的。
16   // 判斷$gis_data[‘gis_type’]是否已經存在
17   if (! isset($gis_data['gis_type'])) {
18       if (isset($_REQUEST['type']) && $_REQUEST['type'] != '') {
19           $gis_data['gis_type'] = strtoupper($_REQUEST['type']);
20       }
21       if (isset($_REQUEST['value']) && trim($_REQUEST['value']) != '') {
22           $start = (substr($_REQUEST['value'], 0, 1) == "'") ? 1 : 0;
23           $gis_data['gis_type'] = substr(
24               $_REQUEST['value'], $start, strpos($_REQUEST['value'], "(") - $start
25           );
26       }
27       if ((! isset($gis_data['gis_type']))
28           || (! in_array($gis_data['gis_type'], $gis_types))
29       ) {
30           $gis_data['gis_type'] = $gis_types[0];
31       }
32   }
33   $geom_type = $gis_data['gis_type'];//賦值
34   // 經過傳遞的值生成參數。
35   $gis_obj = PMA_GIS_Factory::factory($geom_type);//傳參
  • 首先調用了factory函數,而且參數等於$gis_data['gis_type'],第4行:$gis_data = $_REQUEST['gis_data'];獲取到gis_data,判斷$gis_data[‘gis_type’]是否已經存在,若是存在則跳過那 一大串if子句。最後就將$gis_data[‘gis_type’]賦值給$geom_type,並傳入 PMA_GIS_Factory::factory函數。
  • 實際利用方法其實就是獲取$_REQUEST[‘gis_data’][‘gis_type’]並拼接到include_once中,形成任意文件包含。

4.4 修復建議

相關文章
相關標籤/搜索