Skip to content

Command Injection

Command injection is when user input lands in a function that spawns a shell or process, letting you append your own commands. You confirm it with a separator (;, \n, &, |, &&, ||, `, $()), then escalate to enumeration, blind exfiltration, or a reverse shell.

Three vulnerability classes get confused - they need different exploitation:

  • Command injection - input concatenated into a shell invocation. You inject commands. Sinks: PHP system/exec/passthru/shell_exec/popen, Node child_process.exec/spawn (with shell), Python os.system/subprocess.run(..., shell=True), Ruby ` `/Kernel#system, Java Runtime.exec(String) with shell wrapper.
  • Argument injection - input concatenated into a fixed binary’s argv. The binary is locked, but flags and arguments are yours. See Argument injection.
  • Code injection - input passed to a language eval/exec (PHP eval, Python exec, Node Function()). You inject code in the host language, not shell. Out of scope for this section.
  1. Suspect a sink? Any feature that pings, converts, archives, resolves DNS, generates PDFs, processes images, runs git, or invokes external tools is a candidate. → Detection
  2. Output reflected? Use a separator and read the result. → Execution
  3. No output? Confirm blind via timing or out-of-band callback. → Blind & OOB
  4. Filters in the way? Spaces, slashes, command names, or operators blocked. → Filter bypass
  5. Binary fixed but args controlled? Different bug class, same root cause. → Argument injection
  6. Confirmed RCE, want a shell?Reverse shells
  7. In an exam, need a single page?Cheatsheet

Used throughout this section.

PlaceholderMeaning
<TARGET> Target host or URL
<PARAM> Vulnerable parameter name
<ATTACKER> Your host for HTTP/DNS exfil and OOB callbacks (no port - protocol-default)
<LHOST> Your listener host for reverse shells
<LPORT> Your listener port for reverse shells
<CMD> Arbitrary command being injected