Hunting RCE in Modern Stacks
Direct OS command injection still exists, but the modern remote-code-execution surface has moved. The bugs that land today come from the abstractions we added on top of the language — template engines, serializers, parsers, and package managers. This is where we hunt.
Server-side template injection (SSTI)
Any place user input is concatenated into a server-side template is a candidate. The tell is a mathematical payload rendering: submit {{7*7}} (Jinja/Twig), ${7*7} (FreeMarker/Spring EL), #{7*7} (Ruby), <%= 7*7 %> (ERB). A reflected 49 means you're inside the engine, not just the HTML.
- Find the injection in anything that gets rendered back: display names, email templates, PDF/report generators, error pages, "custom message" fields, admin-configurable copy.
- Fingerprint the engine (each has distinct syntax and error strings), then walk the documented sandbox-escape chain for that engine to reach
Runtime.exec/os.system/ subprocess. - The highest-value SSTI is in template features exposed to low-privilege users — a "customize your notification" box that turns out to be a live template.
Insecure deserialization
When a server rebuilds an object from attacker-controlled bytes, a gadget chain can turn "load this object" into "run this code." Look for:
- Serialized blobs in cookies, hidden fields, caches, and message queues — Java (
rO0base64,AC ED 00 05magic), .NET (ViewState,BinaryFormatter), Python (pickle), Ruby (Marshal), PHP (O:inunserialize), and Node (node-serialize). - The move: identify the framework, then reach for the known gadget chains present in its dependency tree. The vulnerability is deserializing untrusted input at all; the gadget is just the delivery.
Dependency and build-chain RCE
Increasingly, the code you run is code you didn't write:
- Dependency confusion — an internal package name that isn't claimed on the public registry lets an attacker publish a malicious public version the build pulls instead.
- Lockfile and CI injection — a
postinstallscript, a poisoned dependency, or an injectable build variable that runs in the pipeline. CI runs with credentials; RCE in the build is RCE in production's supply chain. - Known-vuln dependencies — an outdated parser/serializer/image library with a public RCE. Fingerprint versions from behavior and error strings, then match to advisories.
File-processing pipelines
Anywhere an upload is parsed rather than merely stored:
- Image/media libraries (ImageMagick-style delegate abuse, ffmpeg, PDF renderers) that shell out or resolve remote resources.
- Document parsers — Office/XML with external entity and macro-adjacent processing; SVG that reaches template or script contexts.
- Archive handling — path traversal on extraction (
../../) that writes a file into a code path that later executes (a webshell into the web root, a cron/config file, an overwritten binary).
The methodology, compressed
- Inventory every parser and renderer the input touches — templates, serializers, media/doc processors, archive extractors, the dependency graph.
- Fingerprint the exact engine/library and version.
- Prove execution with the most benign primitive — a DNS callback from the target, a
sleepthat measures, aid/whoamiechoed once. Never a shell, never persistence, never lateral movement on someone else's box. - Stop at proof. One out-of-band ping that only your infrastructure sees is a complete, undeniable demonstration of RCE. Everything past it is risk with no added value.
Modern RCE is rarely a ; in a parameter. It's trusting attacker bytes at a layer that was powerful enough to run them. Find the powerful layer, and the input that reaches it.