本文假设你对Java基本数据结构、Java反序列化、高级特性(反射、动态代理)等有一定的了解。

背景

YsoSerial是一款反序列化利用的便捷工具,可以很方便的生成基于多种环境的反序列化EXP。java -jar ysoserial.jar 可以直接查看payload适用环境及其适用版本。

关于此工具的背景,我引用P神的《Java安全漫游》文章对其的描述:

2015年Gabriel Lawrence (@gebl)和Chris Frohoffff (@frohoffff)在AppSecCali上提出了利⽤Apache Commons Collections来构造命令执⾏的利⽤链,并在年底因为对Weblogic、JBoss、Jenkins等著名应⽤的利⽤,⼀⽯激起千层浪,彻底打开了⼀⽚Java安全的蓝海。⽽ysoserial就是两位原作者在此议题中释出的⼀个⼯具,它可以让⽤户根据⾃⼰选择的利⽤链,⽣成反序列化利⽤数据,通过将这些数据发送给⽬标,从⽽执⾏⽤户预先定义的命令。

下载工具源码发现主要payload生成逻辑都在ysoserial.payloads包下面:

接下来主要针对 URLDNS、 CommonCollections1-7、CommonsBeanutils 利用链进行分析:

URLDNS

URLDNS 是要介绍的几条链中调用逻辑最简单的一条,所以以这条链开始。我们来看看yso是怎么写的

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;
}

getObject方法就是获取最后的利用类,return的是一个以精心构造的URL对象为key,url字符串为值的hashMap,调试一下看下调用链。

HashMap.readOject -> HashMap.hash() -> URLStreamHandler.hashCode() -> URLStreamHandler.getHostAddress()(获取url的dns地址)

  1. HashMap.readOject()

readObject中有读取key,然后对key进行hash操作,从yso代码得知,hashmap的key为精心构造的URL对象

private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException {
// Read in the threshold (ignored), loadfactor, and any hidden stuff
s.defaultReadObject();
s.readInt(); // Read and ignore number of buckets
int mappings = s.readInt(); // Read number of mappings (size) ....
....
// 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);
}
}
}
  1. HashMap.hash()

跟进hash,里面调用了URL对象的hashCode()方法。

    static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
  1. URL.hashCode()

URL对象的存在默认的私有hashCode变量其值为-1,所以会调用yso代码中URL对象构造方法的第三个参数,URLStreamHandler的hashcode。

  public synchronized int hashCode() {
if (hashCode != -1)
return hashCode; hashCode = handler.hashCode(this);
return hashCode;
}
    private int hashCode = -1;
  1. URLStreamHandler.hashCode()

然后调用URLStreamHandler的getHostAddress()方法

protected int hashCode(URL u) {

...
// Generate the host part.
InetAddress addr = getHostAddress(u);
... return h;
}
  1. URL.getHost()

getHost 就会发起对应url的请求,后续就不用再跟了。

rotected synchronized InetAddress getHostAddress(URL u) {
...
String host = u.getHost();
...
return u.hostAddress;
}

以上就是URLDNS的调用逻辑,但是在yso中还是有两个点值得我们注意:

  1. Reflections.setFieldValue(u, "hashCode", -1); 这一行代码是干嘛的,是多余的吗?
  2. 为什么SilentURLStreamHandler 会实现两个空方法?

首先第一个问题,这一行代码是干嘛的,为什么要将URL对象中的hashcode通过反射的方式设置为-1呢,URL对象中的hash code本身就是-1,为什么要这么做?

​ 其实通过代码中的注释我们也能知道,在hashMap进行put操作时,会调用hash()方法,进而完成了一次类似反序列化的调用,handler调用hashcode()方法时也会将默认的hashCode值进行重新计算,所以put()完,本身的hashCode已经不为-1了,所以反序列就不会在继续执行handler.hashCode(this),也就没发触发DNS请求。

  public synchronized int hashCode() {
if (hashCode != -1)
return hashCode; hashCode = handler.hashCode(this);
return hashCode;
}

第二个问题,其实和第一个问题一样,在put时也会进行一次hash()调用从而进行一次dns请求,为了避免在生成payload对象时候发起dns请求,所以继承了URLStreamHandler,实现getHostAddress、openConnection两个方法进行空操作,进而在生产payload对象时就不会发器dns请求了。

刚开始看到这里的时候我比较疑惑,重写了这两个方法到时候在使用这个payload去利用的时候不就没发正常发起DNS请求了吗,那这样做意义何在?原来我忽略了一个东西,在URL类中,URLStreamHandler被transient关键字标记,transient标记的属性在序列化时不会带入序列化的数据里面,这样在生成payload或者调试的时候不会发起DNS请求,但又不影响payload的正常使用,非常巧妙。

总结

URLDNS是一个不需要依赖其他包的反序列化利用,且调用过程比较简单,只会在HashMap与StreamHandler之间调用,稍微需要注意的也就是亮点,一个为什么要将hashcode最后通过反射的方式置为-1,另一个是为什么重写过StreamHandler两个方法为空操作后仍然能在凡序化后正常发起dns请求。

虽然URLDNS这条链很简单,但其实它做不了什么,仅仅只能帮助我们判断这个地方可能存在用户可控的凡序列化问题,仍然不能进行进一步的利用,那要怎么才能利用乃至RCE呢? 下一专题Common-collections1 就来帮助我们解决这个问题。

YsoSerial 工具常用Payload分析之URLDNS的更多相关文章

  1. YsoSerial 工具常用Payload分析之CC1

    前文介绍了最简单的反序列化链URLDNS,虽然URLDNS本身不依赖第三方包且调用简单,但不能做到漏洞利用,仅能做漏洞探测,如何才能实现RCE呢,于是就有Common-collections1-7.C ...

  2. YsoSerial 工具常用Payload分析之CC5、6(三)

    前言 这是common-collections 反序列化的第三篇文章,这次分析利用链CC5和CC6,先看下Ysoserial CC5 payload: public BadAttributeValue ...

  3. YsoSerial 工具常用Payload分析之Common-Collections7(四)

    前言 YsoSerial Common-Collection3.2.1 反序列化利用链终于来到最后一个,回顾一下: 以InvokerTranformer为基础通过动态代理触发AnnotationInv ...

  4. YsoSerial 工具常用Payload分析之Common-Collections2、4(五)

    前言 Common-Collections <= 3.2.1 对应与YsoSerial为CC1.3.5.6.7 ,Commno-collections4.0对应与CC2.4. 这篇文章结束官方原 ...

  5. YsoSerial 工具常用Payload分析之CC3(二)

    这是CC链分析的第二篇文章,我想按着common-collections的版本顺序来介绍,所以顺序为 cc1.3.5.6.7(common-collections 3.1),cc2.4(common- ...

  6. Java应用常用性能分析工具

    Java应用常用性能分析工具 好的工具有能有效改善和提高工作效率或加速分析问题的进度,笔者将从事Java工作中常用的性能工具和大家分享下,如果感觉有用记得投一票哦,如果你有好的工具也可以分享给我 工具 ...

  7. Fiddler抓取https请求 & Fiddler抓包工具常用功能详解

    Fiddler抓取https请求 & Fiddler抓包工具常用功能详解   先来看一个小故事: 小T在测试APP时,打开某个页面展示异常,于是就跑到客户端开发小A那里说:“你这个页面做的有问 ...

  8. SoapUI、Jmeter、Postman三种接口测试工具的比较分析

    前段时间忙于接口测试,也看了几款接口测试工具,简单从几个角度做了个比较,拿出来与诸位分享一下吧.各位如果要转载,请一定注明来源,最好在评论中告知博主一声,感谢.本报告从多个方面对接口测试的三款常用工具 ...

  9. SoapUI、Jmeter、Postman三种接口测试工具的比较分析——灰蓝

    前段时间忙于接口测试,也看了几款接口测试工具,简单从几个角度做了个比较,拿出来与诸位分享一下吧.各位如果要转载,请一定注明来源,最好在评论中告知博主一声,感谢.本报告从多个方面对接口测试的三款常用工具 ...

随机推荐

  1. NVIDIA空中导航SDK改造5G通信

    NVIDIA空中导航SDK改造5G通信 Transforming Next-Generation Wireless with 5T for 5G and the NVIDIA Aerial SDK N ...

  2. 特斯拉Tesla Model 3整体架构解析(上)

    特斯拉Tesla Model 3整体架构解析(上) 一辆特斯拉 Model 3型车在硬件改造后解体 Sensors for ADAS applications 特斯拉 Model 3型设计的传感器组件 ...

  3. 初具雏形的UL标准侧重于自主车辆的安全性

    初具雏形的UL标准侧重于自主车辆的安全性 Nascent UL standard focuses on autonomous vehicle safety 就任何自主汽车(AV)的安全性进行可信的争论 ...

  4. 源码简析Spring-Integration执行过程

    一,前言 Spring-Integration基于Spring,在应用程序中启用了轻量级消息传递,并支持通过声明式适配器与外部系统集成.这一段官网的介绍,概况了整个Integration的用途.个人感 ...

  5. .Net Core with 微服务 - Consul 注册中心

    上一次我们介绍了 Ocelot 网关的基本用法.这次我们开始介绍服务注册发现组件 Consul 的简单使用方法. 服务注册发现 首先先让我们回顾下服务注册发现的概念. 在实施微服务之后,我们的调用都变 ...

  6. 从 Nginx 优秀的核心架构设计,揭秘其为何能支持高并发?

    目录: 1. Nginx的整体架构 2. Nginx的模块化设计 3. Nginx的请求方式处理 4. Nginx事件驱动模型 5. Nginx进程处理模型 写在前面 Nginx 是一个 免费的,开源 ...

  7. LockSupport中的park()与unpark()

    类注释原文:Basic thread blocking primitives for creating locks and other synchronization classes.意思就是Lock ...

  8. centos7安装JDK、CentOS

    1.安装JDK 1.1查看系统是否已有自带的JDK rpm -qa |grep java rpm -qa |grep jdk rpm -qa |grep gcj 1.2卸载已有安装 如果没有输出信息, ...

  9. 重新整理 .net core 实践篇—————领域事件[二十九]

    前文 前面整理了仓储层,工作单元模式,同时简单介绍了一下mediator. 那么就mediator在看下领域事件启到了什么作用吧. 正文 这里先注册一下MediatR服务: // 注册中间者:Medi ...

  10. Vue项目的开发流程

    我先安装的node.js 1.确认已安装了node.js,可在cmd中输入( node -v和npm -v),如显示出版号,说明安装成功 2.安装webpack 和webpack-cli 在全局下安装 ...