Remote code execution.
Three words that make every security team’s heart rate spike. The category of vulnerability where “impact” stops being a checklist item and becomes a very serious phone call.
I found RCE in a cookie.
Not the session ID. Not a session token. The cookie itself — when deserialized by the server — executed arbitrary code.
I ran sleep 10 on their production server to prove it. The response took 10 seconds. That was the proof.
What Is Insecure Deserialization
Applications often need to store complex objects — user preferences, session state, shopping carts — somewhere persistent. One approach: serialize the object to a byte string, store it in a cookie or database, deserialize it when you need it back.
Serialization formats encode not just data but sometimes type information — what class this object is, what methods it has. When you deserialize, the runtime reconstructs the object including its class.
The vulnerability: if an attacker can modify the serialized data before it’s deserialized, they can substitute a different class with different behavior. A class whose constructor, destructor, or magic methods execute arbitrary code when the object is created or destroyed.
In Java, Python’s pickle, PHP’s unserialize, Ruby’s Marshal — all have this problem. The deserialization process is powerful by design. That power is dangerous when the input isn’t trusted.
Finding It
The target — redacted-portal.com — was a legacy enterprise portal. Java backend, clearly old. The session cookie was not an opaque token — it was a Base64 string that decoded to recognizable Java serialization bytes: aced 0005 — the Java serialization magic bytes.
I recognized them immediately.
Whenever you see aced0005 (or its Base64 equivalent rO0AB) in a cookie, you’re looking at a Java serialized object. And Java deserialization is one of the most well-documented RCE surfaces in existence.
The tooling for this is mature: ysoserial generates gadget chain payloads for dozens of common Java libraries. If the target application has any of those libraries on the classpath — and most enterprise Java apps have all of them — you have RCE.
I generated a time-delay payload using ysoserial’s CommonsCollections6 gadget chain:
java -jar ysoserial.jar CommonsCollections6 'sleep 10' | base64
Replaced my session cookie with the output.
Sent the request.
Response time: 10.3 seconds.
The server had deserialized my payload and executed sleep 10.
Remote code execution on a production Java server via a modified cookie.
Stopping Before It Got Real
At this point, a different person might run whoami, cat /etc/passwd, id, check what permissions the Java process had.
I did not do this. I had proven RCE. sleep 10 is sufficient proof. The time delay is unambiguous. No other reasonable explanation for a 10-second delay on a command that normally takes 300ms.
I didn’t need to know what user the server ran as. I didn’t need to read any files. I didn’t need to make any further calls.
The report writes itself from sleep 10. Everything else is risk with no additional reward.
The Report and Response
Title: Insecure Java Deserialization in Session Cookie — Remote Code Execution via CommonsCollections6 Gadget Chain (Confirmed via Time-Delay Payload)
Severity: Critical — Remote Code Execution
CVSS: 10.0
Impact: The session cookie contains a Java serialized object that is deserialized server-side without integrity verification. Using ysoserial with a CommonsCollections6 gadget chain, arbitrary operating system commands can be executed in the context of the application server process. Confirmed via a sleep 10 time-delay payload producing a consistent 10.3 second response time versus baseline of 0.3 seconds.
Remediation: Never deserialize untrusted data. If serialization is required for session state, use a cryptographically signed format (HMAC-signed JSON, encrypted JWT) that cannot be modified by the client. If Java serialization is unavoidable, implement a deserialization filter (Java 9+ serialization filters) that allowlists permitted classes.
Response time: 2 hours. Triage: Critical. Fix timeline: 72 hours (required replacing the session handling mechanism entirely — not a quick patch).
Bounty: $$$$
The Lesson Nobody Wants to Hear
Don’t deserialize user-controlled data. Full stop.
This isn’t a subtle misconfiguration. This isn’t a missing header. This is a fundamental architectural decision: trusting client-supplied serialized objects as safe to deserialize.
The cookie is client-controlled. The client is the adversary. Deserializing attacker-controlled bytes and having the runtime reconstruct classes from them is one of the most dangerous things an application can do.
If you’re maintaining a Java application with cookie-based session serialization and you haven’t audited this: stop reading and go check.
Reported through the official bug bounty program. The only payload executed was sleep 10. No files were read, no commands beyond the time-delay PoC were run, no persistence was established. Domain redacted per responsible disclosure norms.