作者: 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分為服務端和客戶端,客戶端連接服務器使存在三種方法:
- Unix套接字;
- 內存共享/命名管道;
- 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 參考鏈接
- http://codingo.xyz/index.php/2017/12/27/mysql_protocol/
- http://vinc.top/2017/04/19/mysql-udf%E6%8F%90%E6%9D%83linux%E5%B9%B3%E5%8F%B0/
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/510/
暫無評論