CommonsCollections3
Apache Commons Collections 是一个扩展了 Java 标准库里的 Collection 结构的第三方基础库,它提供了很多强有力的数据结构类型并实现了各种集合工具类。作为 Apache 开源项目的重要组件,被广泛运用于各种 Java 应用的开发。
调用链
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 8u71以下
cc3 为了避免使用InvokerTransformer
寻找了一个新类去调用 newTransformer()
com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter
这个类的构造函数中
TrAXFilter 在实例化时接收 Templates 对象,并调用其 newTransformer 方法,这就可以触发我们的 TemplatesImpl 的攻击 payload 了
TemplatesImpl的构造链是java自带的一个类他可以调用defineClass方法去加载任意字节码并且在getTransletInstance()
方法中使用 newInstance()
实例化,这样就可以调用字节码中的构造函数或静态代码块。
但是这个类对于加载的类有要求,要求其父类为com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet
这点很重要,一定要记得设置父类。
那么现在就需要再找一个类去触发TrAXFilter 的构造函数,这里用到了Transformer:InstantiateTransformer,他可以通过反射去创建类示例并触发其构造函数,然后再用cc1的前半段去让整个链子串起来。
1 | InputStream inputStream = Test.class.getResourceAsStream("Evil.class"); |
这里因为也使用了cc1的前端,所以受AnnotationInvocationHandler
这个类改动的影响
那么是否存在一个方法可以代替这个类扩宽我们的攻击面呢,所以就出现了cc6这条链子
CommonsCollections6
调用链
Gadget chain:
java.io.ObjectInputStream.readObject()
java.util.HashMap.readObject()
java.util.HashMap.hash()
org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode()
org.apache.commons.collections.keyvalue.TiedMapEntry.getValue()
org.apache.commons.collections.map.LazyMap.get()
org.apache.commons.collections.functors.ChainedTransformer.transform()
org.apache.commons.collections.functors.InvokerTransformer.transform()
java.lang.reflect.Method.invoke()
java.lang.Runtime.exec()
基本可以通杀jdk7,8
其实要解决高版本的问题也就是要找到其他他调用LazyMap#get() 的地方
这里大师傅们找到了类 org.apache.commons.collections.keyvalue.TiedMapEntry
在其getValue方法
中调用了 this.map.get ,其hashCode调用了getValue方法
通过这里就可以去触发lazymap的get方法,所以现在就找那里可以触发TiedMapEntry#hashCode
,这里是发现的在 java.util.HashMap#readObject
中可以触发hashCode
这里传入key对象,就可以触发key的hashCode方法
在ysoserial中是利⽤ java.util.HashSet#readObject 到 HashMap#put() 到 HashMap#hash(key)
最后到 TiedMapEntry#hashCode() 。我这里跟进p神的简化链直接编写exp了。
1 | Transformer[] chain = new Transformer[]{ |
这里cc6的利用链也完成了
然后自己根据cc6去改了下cc3让他可以通杀java7,8
1 | InputStream inputStream = Test.class.getResourceAsStream("Evil.class"); |
无数组构造
在有次比赛中有提到无数组的反序列化链构造,这也是因为有tomcat内部对类处理有问题所以延伸出的问题。
我们的payload都有用到 Transformer
数组,这里可以是过不了的,所以我们这里通过 TemplatesImpl 去构造不含数组的exp
主要的知识点也就是
这里key会直接进入transform的参数中这样我们就不需要在
这里面的第一句,只用第2句调用方法,这样也就不需要数组的形式了。然后这里的key也就是我们在这传入的key
1 | InputStream inputStream = Test.class.getResourceAsStream("Evil.class"); |
参考链接
java安全漫谈