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下载 解压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
- 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?