Deserialization and Server-Side Template Injection
When data becomes objects or code
Deserialization is dangerous because the format lets a caller define object type and properties. In PHP, unserialize on user data triggers magic methods (__wakeup, __destruct, __toString), and a POP chain strings harmless gadgets together until a dangerous sink fires. The entry point need not be an obvious unserialize call: a PHAR archive can trigger deserialization when any file function touches a phar:// path, and cookies or hidden fields often carry base64 serialized blobs. In Java, gadget chains are assembled from libraries on the classpath; in Python, pickle is effectively code execution by design; Node has its own unsafe deserialization packages.
SSTI begins when user input is concatenated into a template string rather than passed as a variable. Fingerprint the engine with arithmetic polyglots ({{7*7}}, ${7*7}, <%= 7*7 %>, #{7*7}) and identify version-specific escapes. Engines leak built-in objects: Jinja2 reaches Python internals through the MRO chain (''.__class__.__mro__), Twig has _self and filter gadgets, Freemarker and Velocity expose their own object graphs. Sandboxes are escape-prone; look for documented bypasses for the specific version.
Traps: confusing SSTI with XSS (the payload runs server-side); assuming a sandbox blocks everything; forgetting that deserialization needs a gadget already present in the codebase; and missing that a custom cookie format or remember-me token is serialized data.
Rule of thumb: any parameter whose value looks like O:4:"..." base64-encoded, or that is rendered by a template engine, deserves a controlled test with a harmless arithmetic payload first.