与CC1和CC6不同,CC1、6是Runtime命令执行,CC3是动态类加载,能够任意代码执行。
回顾:TemplatesImpl
CC3的sink点在于 defineClass()
。但如果只是加载恶意类不初始化的话,是不会执行代码的,因此还需要一个 newInstance
初始化的操作。之前学习动态加载字节码的时候也了解到,defineClass()
往往都是 protected类型的,实战中很少能接触到。但是有TemplatesImpl
,它的内部类TransletClassLoader
继承ClassLoader
并重写了defineClass()
方法。这里defineClass
没有声明权限修饰符,所以这里的defineClass
由其父类的 protected 类型变成了一个 default 类型的方法,可以被类外部调用。
调用链:
|
|
追到最前面两个方法TemplatesImpl#getOutputProperties()
和TemplatesImpl#newTransformer()
,这两者的作用域都是public,可以被外部调用。这里就通过newTransformer
方法来调用defineClass
CC1+TemplatesImpl
CC1是利用invoke
反射调用Runtime().getRuntime().exec()
执行命令,不过很多时候服务器的代码当中的黑名单会选择禁用Runtime
。
|
|
那么可以想到将CC1中InvokerTransformer
执行的方法替换成TemplatesImpl::newTransformer()
|
|
成功执行字节码
CC6+TemplatesImpl
同理,CC6也可以和TemplatesImpl
结合起来
TrAXFilter
上述都是通过TemplatesImpl.newTransformer()
来加载恶意类,还可以继续往上找,看其他调用newTransformer()
的地方。ysoserial
作者考虑到InvokerTransforme
的使用上了黑名单,于是找到另外一个类com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter
。这个类的构造方法中调用了(TransformerImpl) templates.newTransformer()
,免去了我们使用 InvokerTransformer
手工调用 newTransformer()
。
没有了InvokerTransformer
,想要调用TrAXFilter
的构造方法,会用到新的类——org.apache.commons.collections.functors.InstantiateTransformer
,它实现了Transformer
接口,提供调用构造方法的功能。
编写POC
替换InvokerTransformer
|
|
成功触发
参考:
- phith0n-java代码审计
- https://www.cnblogs.com/1vxyz/p/17458691.html