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:

  1. 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, preferences is the prime suspect.

  2. 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.

  3. 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 ysoserial are invaluable here.

    Let’s say you’re targeting a Java application. You’d use ysoserial to generate a payload. For example, to create a payload that executes touch /tmp/pwned on the server:

    java -jar ysoserial.jar CommonsBeanutils1 'touch /tmp/pwned' > payload.ser
    

    This generates a file named payload.ser containing the malicious serialized Java object.

  4. Encode and Substitute: Take the generated payload.ser file, read its contents, and Base64 encode it.

    cat payload.ser | base64
    

    This will give you a long string. Let’s say it’s rO0ABX.... Now, substitute this into the original request, replacing the legitimate preferences value:

    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>..."
    }
    
  5. Send and Observe: Send this modified request through Burp Repeater. If the server deserializes the preferences parameter without validation, you’ll likely see an error, or if you’re lucky, the command will execute. For our touch /tmp/pwned example, you’d need to check the server’s filesystem for the /tmp/pwned file. If you get a stack trace indicating an Unserializable exception 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 CommonsBeanutils1 doesn’t work, try other ysoserial gadgets like CommonsCollections1, JRMPClient, etc., depending on the libraries your target application uses. You can often guess libraries by looking at the Content-Type of 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.

Want structured learning?

Take the full Burpsuite course →