Burp Suite’s built-in scanner can’t find insecure deserialization vulnerabilities because it doesn’t know what "good" and "bad" deserialized objects look like.
Let’s see how to hunt for these manually. Imagine you’re interacting with a web app, and you notice a request that looks something like this:
POST /api/user/profile HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/json
Content-Length: 123
{
"userId": 12345,
"preferences": "eyJ1c2VySWQiOjEyMzQ1LCJ0aGVtZSI6ImxpZ2h0In0="
}
The preferences parameter is a Base64 encoded string. This is a common pattern for storing serialized objects. The Base64 hides the complexity, but the underlying data is likely a serialized Java object, Python pickle, or similar. If the application blindly deserializes this string without validation, we can craft a malicious object that, when deserialized, executes arbitrary code on the server.
The core problem is that deserializing untrusted data is like opening a present from a stranger. You don’t know what’s inside, and it could be anything from a nice gift to a bomb. Applications often use serialization to pass complex data structures between different parts of the system or to store state. If an attacker can control the serialized data, they can inject code that runs when the application tries to "unpack" it.
Here’s how you’d hunt for this with Burp Suite:
-
Identify Potential Targets: Look for request parameters that contain Base64 encoded strings, JSON/XML blobs, or other data structures that might be serialized. Common places are cookies, custom headers, or parameters in POST/GET requests. In our example,
preferencesis the prime suspect. -
Decode and Inspect: Use Burp’s "Decode selected text" feature (right-click in the Repeater tab) to decode Base64 or other encodings. You’ll often see something like this if it’s a JSON representation of a serialized object:
{"userId":12345,"theme":"light"}If it’s a binary format like Java serialization, it will look like gibberish, which is fine. You know it’s binary data.
-
Craft a Gadget Payload: This is where the real work begins. You need to find a "gadget chain" – a sequence of existing objects within the application’s dependencies that, when deserialized in a specific order, leads to code execution. Tools like
ysoserialare invaluable here.Let’s say you’re targeting a Java application. You’d use
ysoserialto generate a payload. For example, to create a payload that executestouch /tmp/pwnedon the server:java -jar ysoserial.jar CommonsBeanutils1 'touch /tmp/pwned' > payload.serThis generates a file named
payload.sercontaining the malicious serialized Java object. -
Encode and Substitute: Take the generated
payload.serfile, read its contents, and Base64 encode it.cat payload.ser | base64This will give you a long string. Let’s say it’s
rO0ABX.... Now, substitute this into the original request, replacing the legitimatepreferencesvalue:POST /api/user/profile HTTP/1.1 Host: vulnerable-website.com Content-Type: application/json Content-Length: 150 { "userId": 12345, "preferences": "rO0ABX...<your_encoded_payload_here>..." } -
Send and Observe: Send this modified request through Burp Repeater. If the server deserializes the
preferencesparameter without validation, you’ll likely see an error, or if you’re lucky, the command will execute. For ourtouch /tmp/pwnedexample, you’d need to check the server’s filesystem for the/tmp/pwnedfile. If you get a stack trace indicating anUnserializableexception or similar, it’s a strong indicator you’re on the right track, but it means the specific gadget chain you used was blocked or not present.You need to iterate on step 3. If
CommonsBeanutils1doesn’t work, try otherysoserialgadgets likeCommonsCollections1,JRMPClient, etc., depending on the libraries your target application uses. You can often guess libraries by looking at theContent-Typeof error responses or by analyzing the application’s JavaScript files for clues about backend technologies.
The most surprising true thing about insecure deserialization is that the vulnerability often doesn’t lie in the application’s own code, but in the behavior of standard library classes or popular third-party libraries that were never intended to be used in a security-sensitive way during deserialization. The "gadget chains" leverage the fact that deserializing a crafted object can trigger arbitrary method calls on other objects already loaded in memory, and by chaining these calls, an attacker can achieve code execution.
The next thing you’ll run into is figuring out how to bypass specific deserialization filters or defenses that might be in place.