JNDI注入工具代碼結構分析
該文章首發于Sec-IN,文章鏈接:https://www.sec-in.com/article/1632
工具鏈接:https://github.com/Jeromeyoung/JNDIExploit-1
如下是一些模塊的作用:
controllers模塊:負責LDAP請求的處理

enum模塊:負責存儲各種模板類型名稱,如:反序列化的Gadget、內存馬的類型

異常模塊:負責處理可能拋出的異常

反序列化模塊:各種反序列化鏈的處理

模板模塊:命令執行、回顯、DNS、內存馬模板

工具類模塊:主要是為了方便而編寫的一些工具類

協議服務及啟動模塊:負責LDAP、HTTP協議的具體實現

下面先對啟動及協議服務模塊進行說明

com.feihong.ldap.Starter類為整個工具的啟動入口,從命令行接收參數傳參到com.feihong.ldap.utils.Config類

Config類中的@Parameter注解為參數的說明及代表的意思,類似于py中的argparse,命令接收到參數,分別賦值給Config類的幾個私有變量。
然后在之后的HTTPServer與LDAPServer中得到應用

關于LDAP服務端的編寫和Demo可以參考以下鏈接:https://www.freebuf.com/vuls/253545.html,
HTTPServer則是正常的Java Demo編寫即可

THE SPRING EQUINOX
注解的應用
在JNDIEXP中,作者為了可以反射一種類型的類,Controller類,這里的類起到了尋找特定類的作用,而且每個注解類都給定了uri屬性

在LDAPServer.start()之前,會先通過new Reflections(this.getClass().getPackage().getName())的方法獲取到com.feihong.ldap包下面所有LdapMapping的類,之后將其以鍵值對(TreeMap)放入到Map中,以便于后續調用

比如com.feihong.ldap.controllers.BasicController類,在Map中的存儲格式就是(basic=>Object BasicController)

根據發送來的LDAP請求去決定調用哪個類,具體通過com.feihong.ldap.processSearchResult

根據工具運行的實際效果,如果我們的LDAP請求為ldap://192.168.85.1:1389/Basic/123

那么DN為Basic/123,首先根據DN中的開頭字符串決定是哪個Controller來處理當前的LDAP的請求
THE SPRING EQUINOX
服務端動態調用類
在LDAP調用LdapController接口實現類之后(以BasicController為例),會先調用process方法,以/為標志分割,獲取到相應的模塊名稱,比如ldap://0.0.0.0:1389/Basic/Command/whoami,那么第一部分Basic用來指定是BasicController,Command指定執行BasicController下的命令執行模塊


如果是命令執行模塊

通過com.feihong.ldap.utils.Util的getCmdFromBase方法獲取到執行命令的內容,如果是base編碼的,進行base64解碼后返回內容

將其賦值給params,之后再調用BasicController的sendResult方法,如果是command模塊,初始化該模塊,通過asm碼的方法,這里為了避免出現類名重復的情況,使用隨機字符命令類名





之后命令執行模塊調用cache方法



將其存儲在map中,之后開始進行LDAP的步驟

首先LDAP設定好
javaClassName:記錄序列化對象的類名,這樣應用程序就可以確定類信息,而不必首先反序列化
javaClassNames:關于序列化對象的附加類信息。
javaCodebase:實例化工廠所需的類定義的位置(HTTP地址)
javaFactory:用于存儲對象工廠的完全限定類的可選屬性(即類名)
一張圖說明LDAP請求的過程

接下來看HTTPServer如何接收HTTP請求并返回

當HTTPServer接收到請求之后,將Cache類中map存儲的類寫入到響應中,這樣避免了class文件落地的情況。
版權申明:內容來源網絡,版權歸原創者所有。除非無法確認,都會標明作者及出處,如有侵權,煩請告知,我們會立即刪除并致歉!