中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java JDBC導致的反序列化攻擊原理解析

發布時間:2020-09-29 07:42:44 來源:腳本之家 閱讀:169 作者:Welk1n 欄目:編程語言

這篇文章主要介紹了Java JDBC導致的反序列化攻擊原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

背景

上周BlackHat Europe 2019的議題《New Exploit Technique In Java Deserialization Attack》中提到了一個通過注入JDBC URL實現反序列化攻擊的場景,簡單分析一下。

分析

首先,當java應用使用MySQL Connector/J(官方的JDBC驅動,本文基于其8.0+版本)連接mysql時,JDBC URL的格式如下:protocol//[hosts]/[database]?properties,具體可看mysql官方文檔,示例:jdbc:mysql://localhost:3306/test?useSSL=true

其中,protocol、host、database都比較好理解,URL中的properties可以設定MySQL Connector/J連接mysql服務器的具體方式,關于properties的官方文檔地址,其中和本文相關的連接屬性有兩個,分別是autoDeserialize和queryInterceptors,前者是設定MySQL Connector/J是否反序列化BLOB類型的數據,后者是攔截器,在查詢執行時觸發,由com.mysql.cj.protocol.a.NativeProtocol#sendQueryPacket方法源碼可知,會在執行查詢語句前后分別調用攔截器的preProcess和postProcess方法。

接下來定位下反序列化的觸發點,在mysql-connector-java組件下全局搜索關鍵字“.readObject()”,定位到com.mysql.cj.jdbc.result.ResultSetImpl類中的getObject(int columnIndex)方法,部分核心代碼如下:

public Object getObject(int columnIndex) throws SQLException {
……
case BLOB:
 byte[] data = getBytes(columnIndex);
 if (this.connection.getPropertySet().getBooleanProperty(PropertyDefinitions.PNAME_autoDeserialize).getValue()) {
   Object obj = data;
   // Serialized object?
   try {
    ByteArrayInputStream bytesIn = new ByteArrayInputStream(data);
    ObjectInputStream objIn = new ObjectInputStream(bytesIn);
    obj = objIn.readObject();
   }
 }
}

變量data即為mysql返回結果集,當JDBC URL中設定屬性autoDeserialize為true時,會對類型為bit、binary以及blob的數據進行反序列化,如何觸發getObject(int columnIndex)方法的調用呢?議題中給出的調用鏈如下:

> com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor#preProcess/postProcess
> com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor#populateMapWithSessionStatusValues
> com.mysql.cj.jdbc.util.ResultSetUtil#resultSetToMap
> com.mysql.cj.jdbc.result.ResultSetImpl#getObject

ServerStatusDiffInterceptor即為此前提到過的攔截器,在JDBC URL中設定屬性queryInterceptors為ServerStatusDiffInterceptor時,執行查詢語句會調用攔截器的preProcess和postProcess方法,進而通過上述調用鏈最終調用getObject(int columnIndex)方法。

實際利用還有一個問題,最終調用getObject方法的對象是數據庫返回的結果集,由populateMapWithSessionStatusValues方法可知:

try {
  toPopulate.clear();

  stmt = this.connection.createStatement();
  rs = stmt.executeQuery("SHOW SESSION STATUS");
  ResultSetUtil.resultSetToMap(toPopulate, rs);
}

這個結果集是執行SQL語句“SHOW SESSION STATUS”后數據庫返回的值,SQL語句“SHOW SESSION STATUS”返回當前數據庫連接的狀態值,實際是讀取系統表INFORMATION_SCHEMA.SESSION_VARIABLES的值,也可能是PERFORMANCE_SCHEMA.SESSION_VARIABLES(Mysql版本差異導致)。但是mysql中INFORMATION_SCHEMA和PERFORMANCE_SCHEMA都是不允許被修改的,所以需要想辦法操縱返回的數據。

利用條件

1.本質上還是Java原生的反序列化利用,所以需要環境中有可用的Gadget;

2.需要能偽造相關系統表的數據,將“SHOW SESSION STATUS”的執行結果設置為我們精心構造的反序列化數據,或者基于mysql連接協議,自定義返回數據,后面有時間的時候會寫寫這塊兒。

3.可控的JDBC URL

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

利津县| 永善县| 平远县| 宁海县| 根河市| 南宫市| 油尖旺区| 阿坝县| 黑河市| 阳信县| 凭祥市| 兰西县| 肥乡县| 沂源县| 资讯| 嘉义市| 宁化县| 旬邑县| 兰西县| 施秉县| 新和县| 双辽市| 寻乌县| 临泽县| 宁河县| 保亭| 白沙| 左贡县| 呈贡县| 皮山县| 中江县| 新密市| 垦利县| 襄汾县| 阿坝县| 龙陵县| 蓬莱市| 正宁县| 凌云县| 长海县| 镇雄县|