作者: xfkxfk@逢魔安全實驗室

01 背景介紹

SSRF(Server-Side Request Forgery)服務端請求偽造,是一種由攻擊者構造形成由服務器端發起請求的一個漏洞,一般情況下,SSRF 攻擊的目標是從外網無法訪問的內部系統。

在互聯網上已經很多介紹SSRF漏洞的原理,漏洞場景,漏洞利用方法的文章,但是大多數的SSRF漏洞利用都是內網掃描,內網服務識別,內網漏洞盲打,寫計劃任務獲取shell,寫私鑰獲取shell,利用SSRF漏洞結合Gohper或者Dict協議攻擊Redis、MongoDB、Memcache等NoSQL,但是很少見有利用SSRF漏洞攻擊內網MySQL、PostgreSQL、MSSQL等關系型數據庫,所以本文我們將介紹如何利用SSRF漏洞結合Gopher系統攻擊內網未授權MySQL,并且獲取系統shell的方法。

02 MySQL通信協議

MySQL連接方式:

在進行利用SSRF攻擊MySQL之前,先了解一下MySQL的通信協議。MySQL分為服務端和客戶端,客戶端連接服務器使存在三種方法:

  1. Unix套接字;
  2. 內存共享/命名管道;
  3. TCP/IP套接字;

在Linux或者Unix環境下,當我們輸入mysql–uroot –proot登錄MySQL服務器時就是用的Unix套接字連接;Unix套接字其實不是一個網絡協議,只能在客戶端和Mysql服務器在同一臺電腦上才可以使用。

在window系統中客戶端和Mysql服務器在同一臺電腦上,可以使用命名管道和共享內存的方式。

TCP/IP套接字是在任何系統下都可以使用的方式,也是使用最多的連接方式,當我們輸入mysql–h127.0.0.1 –uroot –proot時就是要TCP/IP套接字。

所以當我們需要抓取mysql通信數據包時必須使用TCP/IP套接字連接。

MySQL認證過程:

MySQL客戶端連接并登錄服務器時存在兩種情況:需要密碼認證以及無需密碼認證。當需要密碼認證時使用挑戰應答模式,服務器先發送salt然后客戶端使用salt加密密碼然后驗證;當無需密碼認證時直接發送TCP/IP數據包即可。所以在非交互模式下登錄并操作MySQL只能在無需密碼認證,未授權情況下進行,本文利用SSRF漏洞攻擊MySQL也是在其未授權情況下進行的。

MySQL客戶端與服務器的交互主要分為兩個階段:Connection Phase(連接階段或者叫認證階段)和Command Phase(命令階段)。在連接階段包括握手包和認證包,這里我們不詳細說明握手包,主要關注認證數據包。

認證數據包格式如下:

這里以無需密碼認證情況登錄,看看認證數據包內容:

這里Packet Length為整個數據包的長度,Packet Number為sequence_id隨每個數據包遞增,從0開始,命令執行階段遇到命令重新重置為0。這兩個Packet為真個MySQL通協議的基礎數據包。

客戶端請求命令數據包格式如下:

比如這里select* from flag;命令的數據包如下:

03 構造攻擊數據包

通過上面MySQL通信協議的分析,現在需要構造一個基于TCP/IP的數據包,包括連接,認證,執行命令,退出等MySQL通信數據。

環境:

ubuntu174.4.0-62-generic #x86_64

mysql Ver 14.14 Distrib 5.7.20, for Linux (x86_64)

首先我們需要新建一個MySQL用戶,并且密碼為空,使用root用戶登錄mysql后執行如下命令即可:

CREATEUSER ' usernopass'@'localhost';
GRANTUSAGE ON *.* TO ' usernopass'@'localhost';
GRANTALL ON *.* TO ' usernopass'@'localhost';

上面我們新建了一個用戶usernopass,只允許本地登錄,接下來開始抓包分析。

第一步開一個窗口抓包:

root@ubuntu17:/#tcpdump–i lo port 3306 –w mysql.pcay

第二步開一個窗口使用TCP/IP模式連接MySQL服務器:

root@ubuntu17:/#mysql–h 127.0.0.1 –r usernopass

為了抓到更多數據,然后隨便select一個內容,在exit退出。

第三步使用Wireshark打開上面抓到的mysql.pcap包:

打開數據包后過濾mysql數據包,然后隨便選一個mysql數據包郵件追蹤流,TCP流,然后過濾出客戶端發送到MySQL服務器的數據包,將顯示格式調整為原始數據即可,此時獲取的就是整個MySQL客戶端連接服務器并且執行命令到退出發送的數據包內容,如上圖所示。

然后將原始數據整理為一行,并將其url編碼,最后的內容如下圖所示:

將MySQL原始數據進行編碼的腳本如下:

04 利用SSRF獲取Shell

上面我們構造好了一堆TCP數據包,如果需要使用SSRF漏洞來攻擊MySQL的話,那么我們可以使用gopher協議來發送上面的一堆TCP數據包,最后使用curl發送請求即可。

這里我們select了flag表中的數據,最后構造的請求如下:

但是很多情況下,SSRF是沒有回顯的,及時發送了數據而且MySQL也執行了,但是我們看不到執行后的返回數據,最后我們要的是系統的一個shell。

正常情況下,通過MySQL獲取系統shell一般通過selectinto outfile系統文件,或者使用udf來搞,那么這里同樣我們將獲取shell的數據包提取出來,通過gopher協議發送這些數據包同樣可以達到getshell的目的。

通過select xxx into outfile yyy寫shell的數據包獲取方法同上面構造攻擊數據包的過程,將執行完寫文件sql語句的抓包內容提取出來構造好即可,如下圖成功寫shell文件到系統目錄:

通過udf直接執行系統命令過程同樣,執行完一系列導出udf到plugin的命令后,即可直接執行系統命令執行,如下圖所示反彈shell:

(注意:在導出文件時,當前mysql用戶必須存在file權限;部分MySQL服務器運行時啟用了--secure-file-priv選項,導出文件時只能導出到規定的目錄下,一般為/var/mysql/data命令,要自定義目錄時必須修改配置文件設置secure-file-priv = “”;并且導入目錄需要有寫權限。)

05 實戰演練

例如下面這段常見的php代碼,經常在審計代碼時,遇到這類問題導致的SSRF漏洞,通過這里的SSRF,如果存在未授權的MySQL即可利用上面的攻擊方法獲取數據庫敏感信息,甚至獲取系統shell。

將我們構造好的獲取信息的請求發送到url參數,結果如下:

可以看到成功獲取到了表中的信息,利用導出文件或者udf獲取系統shell的方法一樣,只要構造好數據包直接發送即可。

此方法再前不久的一個CTF中就有一個SSRF題目,就是利用未授權的MySQL獲取數據庫中的信息。

06 其他

這里我們只是介紹了如何構造MySQL數據庫的數據包,并通過SSRF漏洞進行利益,其實他的關系數據庫只要滿足類似的場景都是可以利用的,比如PostgreSQL同樣可以通過此過程進行攻擊,PostgreSQL數據庫的具體利用過程這里不再講解,請期待后續相關內容介紹。

07 參考鏈接


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/510/