Server-side attacks and the file system
Log in Join

Lesson 8 · Reading · 35 min

Deserialization and vulnerable components

Log in to track progress Everything here is free to read without an account.

The last two server-side ideas are about trusting things you should not: trusting a serialized object enough to rebuild it, and trusting a third-party library that turns out to have a published hole. Both can end in code execution, and both are exam-relevant.

Insecure deserialization: a crafted serialized object triggers a gadget chain

Serialization, and why rebuilding is dangerous

To store or transmit an object, a program serializes it, turns the in-memory object into a string of bytes. Later it deserializes: rebuilds the object from those bytes. The danger: if the bytes came from you (a cookie, a hidden field, an API value), and the app rebuilds them without care, you control what object gets constructed. During reconstruction, many languages run code automatically (constructors, "wakeup"/"readObject" hooks, destructors), so a crafted serialized blob can trigger existing methods in an order the developer never intended, a gadget chain: and steer it toward writing a file or running a command.

The key insight: you are not injecting new code, you are stitching together code already present in the app and its libraries, so that reconstructing your object runs it. Publicly available gadget-chain tools (ysoserial for Java, phpggc for PHP) generate these payloads for common libraries.

Spotting deserialization

Look for serialized data crossing the trust boundary, and learn the formats' tell-tales:

  • PHP: strings like O:8:"UserData":2:{...} (often base64-encoded) in cookies or fields.
  • Java: base64 beginning rO0AB (the serialized-stream header), or a Content-Type of application/x-java-serialized-object.
  • Python: pickled data, sometimes base64; .NET has its own ViewState/BinaryFormatter forms.
  • Generally: base64 blobs in cookies, hidden fields, tokens, or API bodies that decode to structured object data rather than plain JSON.

If you find one, the questions are: does the server deserialize it (change a byte, does it error like a broken object?), and does a known gadget chain exist for the libraries in use?

Testing it, honestly

Start by proving the app deserializes your input at all (tampering breaks it in a deserialization-specific way). Then, only on an authorised target, use the gadget-chain tools for the identified language/libraries to build a proof payload, and make it a read-only proof (id, a DNS/HTTP callback to your listener), never destructive. Deserialization RCE is high-impact and easy to break things with, so the gentle-proof rule is firm. On this Academy's labs, go all the way.

Cookie-based object gadgets

A very common practical case: an app stores a serialized object in a cookie (a "preferences" or "remember" cookie) and rebuilds it on each request. If it is not signed, you can craft the object; if the app or its libraries have a usable gadget, that reconstruction runs code. So a serialized cookie is both an integrity problem (you can change your preferences/role, back to the access path) and, potentially, a deserialization RCE.

Vulnerable and outdated components

The other trust here is in libraries. Modern apps are mostly third-party code, frameworks, parsers, serializers, utility libraries, and those have published vulnerabilities. This closes the loop with the recon path's fingerprinting:

  1. Identify the components and versions (fingerprinting, headers, JS bundles, error messages, /vendor paths, lockfiles if exposed).
  2. Match versions to known issues: CVE databases, advisories, the library's changelog. A dependency a few versions behind may carry a documented deserialization RCE, SSRF, or auth bypass.
  3. Confirm reachability. A vulnerable version present in the dependency list is only exploitable if the vulnerable code path is actually reachable in this app. Version-matching is evidence; reproduction is proof.

The most infamous cases, a logging library that executed attacker strings, serialization libraries with public gadget chains, were "just" outdated components, and they compromised enormous numbers of systems. "Exploit vulnerable and outdated components" is a real exam objective and a real-world staple.

The honesty gate

For both: prove the level you reached and no more. A tampered serialized object that changes your role is an access finding; one that runs id is RCE, claim what you showed. For a known-CVE component, report "confirmed exploited" only if you reproduced it; otherwise "running a version with a known issue, likely affected", stating what you verified. Read-only proofs, clean up, authorised targets only.

Your labs

MemoryLane preferences cookie gadget is the cookie-based case: a serialized preferences cookie you can craft into a gadget. ClubTrack bulk-import gadget chain is the fuller chain: a serialized import you turn into execution via a chain of existing code. Do MemoryLane first to see object-from-cookie, then ClubTrack for a real gadget chain.

You have finished the server-side path

You can now recognise the four server-side verbs and exploit each: read files by traversal, run code by upload, command injection, template injection and deserialization, fetch internal resources by SSRF, and read files or reach services through XXE, and you can turn a fingerprinted component into a known finding. Together with Access and Injection, you hold the core of practical web exploitation, from the browser all the way to command execution on the server. The final path, The engagement, is what turns all of this into professional work: methodology, notes, scope, and a report that survives triage.

This lesson has 3 labs to try what you just read.