CC1-TransformedMap

0x01 Environment Build

  • JDK版本:jdk 8u65

  • <dependency>
        <groupId>commons-collections</groupId>
        <artifactId>commons-collections</artifactId>
        <version>3.2.1</version>
    </dependency>

源码里面都是.class文件,反编译的代码不好阅读,需下载.java源码,点击zip下载arrow-up-right 解压jdk8u65的src.zip,将下载后的源码(src\share\classes)的sun文件夹拷贝到解压后的src文件夹

IDEA =》Project Structure =》Platform Settings =》 SDKs =》8u65 =》 SourcePath

另外Maven下载的Commons Collection 也是.class文件,点击Download Sources

若无效试试dependency:resolve -Dclassifier=sources

0x02 Transformer Glance

  • Transformer

    public interface Transformer {
        public Object transform(Object input);
    }

    Transformer是一个接口,预定义的transform()方法能接受任意类型参数 接口下面有几个重要的实现类,且都实现了Serializable接口。

  • ConstantTransformer

    public class ConstantTransformer implements Transformer, Serializable {
        private final Object iConstant;
        public ConstantTransformer(Object constantToReturn) {
            super();
            iConstant = constantToReturn;
        }
        public Object transform(Object input) {
            return iConstant;
        }
    }

    调用transform()方法返回构造时传入的对象 就是传入传出一个对象,前后不变。

  • InvokerTransformer

    public class InvokerTransformer implements Transformer, Serializable {
        public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
            super();
            iMethodName = methodName;
            iParamTypes = paramTypes;
            iArgs = args;
        }
        public Object transform(Object input) {
            if (input == null) {
                return null;
            }
            try {
                Class cls = input.getClass();
                Method method = cls.getMethod(iMethodName, iParamTypes);
                return method.invoke(input, iArgs);
            } // catch ....
        }
    }

    反序列化利用的关键类,可以执行任意方法。

    • iMethodName 待执行的方法名

    • iParamTypes 待执行方法的参数列表的参数类型

    • iArgs 待执行方法的参数列表

    调用transform的时候会执行input对象的iMethodName方法

  • ChainedTransformer

    public class ChainedTransformer implements Transformer, Serializable {
        public ChainedTransformer(Transformer[] transformers) {
            super();
            iTransformers = transformers;
        }
        public Object transform(Object object) {
            for (int i = 0; i < iTransformers.length; i++) {
                object = iTransformers[i].transform(object);
            }
            return object;
        }
    }

    将多个Transformer串成一条链,前一个调用返回的结果作为后一个调用的参数

  • TransformedMap

    public class TransformedMap{
        public static Map decorate(Map map, Transformer keyTransformer, Transformer valueTransformer) {
            return new TransformedMap(map, keyTransformer, valueTransformer);
        }
        protected TransformedMap(Map map, Transformer keyTransformer, Transformer valueTransformer) {
            super(map);
            this.keyTransformer = keyTransformer;
            this.valueTransformer = valueTransformer;
        }
        protected Object checkSetValue(Object value) {
            return valueTransformer.transform(value);
        }
    }

    TransformedMap用于对Java原生Map进行一些修饰,当Map调用setValue时,会触发checkSetValue,进而调用transform。其构造方法被protected修饰,因此我们利用它的静态public方法decorate

0x03 Best Practice

使用Transformer的实现类和TransformedMap实现命令执行

两个问题:

  • Runtime类没有实现Serializable接口,无法反序列化

  • 需要找到readObject中有类似Map.put(xxx,yyy)操作的类

Q1:Class类可以反序列化,用Runtime.class作为ChainedTransformer的入口参数,后面再通过反射来调用exec

Q2:Introducing ~ AnnotationInvocationHandler

memberValue.setValue =》TransformedMap#checkSetValue =》 valueTransformer.transform()

因此让memberValue为上面的evilMap即可。

  • PROBLEM THROW:

    需要满足memberType != null才能进入memberValue.setValue

Class<?> memberType = memberTypes.get(name);

memberTypes👇

name👇

Map<String, Class<?>> memberTypes = annotationType.memberTypes(); String name = memberValue.getKey();

annotationType👇

annotationType = AnnotationType.getInstance(type);

构造函数:

type是构造对象时传进来的Annotation子类Class name是传入Map(memberValues)的每个键名

memberType.get(name)要不为空即要求AnnotationType要有名为name的成员

@Retention和@Target都有value这个成员

另外,AnnotationInvocationHandler的构造方法被default修饰,不能直接new,利用反射来实例化该类

0x04 Weave POC

0x05 CC1 Shortcomings

sun.reflect.annotation.AnnotationInvocationHandler作为CC1链的入口类, 在Java 8u71之后被修改了 修改后的readObject方法中新建了一个LinkedHashMap对象,并将原来的键值添加进去。 所以,后续对Map的操作都是基于这个新的LinkedHashMap对象,而原来我们精心构造的Map不再执 行setValue或put操作,也就不会触发RCE了。

Last updated

Was this helpful?