1. 程式人生 > 實用技巧 >Mysql服務端反向讀取客戶端的任意檔案

Mysql服務端反向讀取客戶端的任意檔案

目錄

1 原理

Mysql服務端反向讀取客戶端的任意檔案
利用LOAD DATA INFILE這個語法,這個語法主要用於讀取一個檔案的內容並且放到一個表中。

load data infile "/data/data.csv" into table TestTable;
load data local infile "/home/lightless/data.csv" into table TestTable;

第一行是讀取服務端本地的檔案,第二行是讀取客戶端本地的檔案
而反向讀取就是利用了第二行用法。
正常流程:

  • s1 客戶端:hi~ 我將把我的 data.csv 檔案給你插入到 test 表中!
  • s2 服務端:OK,讀取你本地 data.csv 檔案併發給我!
  • s3 客戶端:這是檔案內容:balabal!

當s2時,服務端返回給客戶端的不是data.csv,而是其他檔案時,就會發生如下事情

  • s1 客戶端:hi~ 我將把我的 data.csv 檔案給你插入到 test 表中!
  • s2 服務端:OK,讀取你本地的 / etc/passwd 檔案併發給我!
  • s3 客戶端:這是檔案內容:balabal(/etc/passwd 檔案的內容)!

為什麼會這樣?
Mysql官方文件:

“In theory, a patched server could be built that would tell the client program to transfer a file of the server’s choosing rather than the file named by the client in the LOAD DATA statement.”

客戶端讀取哪個檔案其實不是自己說了算,是服務端說了算,也就是以s2時服務端返回的檔案目標為準!

到了這裡有個問題,如果客戶端不主動使用LOAD DATA INFILE,是不是就沒事了呢?
還是官方文件:

"A patched server could in fact reply with a file-transfer request to any statement, not just LOAD DATA LOCAL"

意思就是,偽造的服務端可以在任何時候回覆一個 file-transfer 請求,不一定非要是在LOAD DATA LOCAL的時候。
一些Mysql客戶端,比如python的MySQLdb和mysqlclient,php的mysqli和PDO,java的JDBC Driver以及原生mysql客戶端等等,在連線MySQL的時候,基本上在連線成功之後都會發出一些SELECT語句來查詢一些版本號、編碼之類的資料,這時就可以回覆一個 file-transfer 請求,讀取客戶端上的檔案。
這裡有一點要說明的是,如果想要利用此特性,客戶端必須具有 CLIENT_LOCAL_FILES

屬性,所以可能要新增--enable-local-infile
總結一下漏洞的成因:

  1. LOAD DATA INFILE讀哪個檔案是由服務端返回包的file-transfer 請求決定,而不是客戶端
  2. 不管客戶端發出什麼請求,只要服務端回覆一個 file-transfer 請求,客戶端就會按照LOAD DATA INFILE的流程讀取檔案內容發給服務端

總結一下整個攻擊流程:

  1. 受害者向攻擊者提供的伺服器發起請求,並嘗試進行身份認證
  2. 攻擊者的MySQL接受到受害者的連線請求,攻擊者傳送正常的問候、身份驗證正確,並且向受害者的MySQL客戶端請求檔案。
  3. 受害者的MySQL客戶端認為身份驗證正確,執行攻擊者的發來的請求,通過LOAD DATA INLINE 功能將檔案內容傳送回攻擊者的MySQL伺服器。
  4. 攻擊者收到受害者伺服器上的資訊,讀取檔案成功,攻擊完成。

做個補充:
甚至不需要真的搞個Mysql服務,在mysql客戶端連線時,模仿服務端返回Server Greeting
等待 Client 端傳送一個Query Package後
回覆一個file transfer請求
即可讀取到檔案
復現用的指令碼既是這樣實現

2 條件

  1. 受害者的Mysql客戶端有許可權讀檔案
  2. 受害者的Mysql客戶端設定中,local_infile非0或連線時有用--enable-local-infile,預設是能夠讀取的

3 利用場景

  1. 利用重灌漏洞,讀取目標伺服器上的任意檔案
  2. 利用目標的資料遷移等,能連線外部資料庫的功能點,讀取目標伺服器上的任意檔案
  3. 搭建在蜜罐上讀取攻擊者的資訊,藍隊溯源/反制

4 復現

大佬寫好的指令碼
https://github.com/allyshka/Rogue-MySql-Server
roguemysqlserver.pyfilelist為讀取受害者的檔案地址,讀Win注意路徑
python2執行roguemysqlserver.py,伺服器開放埠和防火牆即可

4.1 mysql原生client

ubuntu18/Win10

  1. 服務端執行roguemysqlserver.py

  2. 客戶端連線
    其實無需密碼即可連線上,即mysql -h 即可連線上

  3. 讀取檔案

4.2 navicat premium12

ubuntu18/Win10

  1. 客戶端

  2. 讀取檔案

4.3 公網測試

嘗試讀取多個檔案時,發現原指令碼所讀檔案不存在時,並不是繼續讀下一個檔案,而是停了下來。。。。
能力有限,不會修改,希望有大佬賜教
一晚上只有幾臺機器連上來,還讀不到檔案就很難受

5 防禦/修復

  1. 使用--ssl-mode=VERIFY_IDENTITY來建立可信的連線
  2. 從配置上防禦
    https://dev.mysql.com/doc/refman/8.0/en/load-data-local-security.html

6 參考

https://lightless.me/archives/read-mysql-client-file.html
https://xz.aliyun.com/t/3973