executeDeployment 额外变量进行操作系统命令注入spawn(cmd[0], cmd.slice(1), { shell: true }) 将参数数组重新拼接成一个
单一的 /bin/sh -c 字符串且未进行转义,因此提供给 executeDeployment MCP 工具的
extraVars 值中的 shell 元字符会在运行该服务器的
主机上执行。
| CVE | CVE-2026-52618 |
| CWE | CWE-78(操作系统命令中使用的特殊元素的不当中和) |
| 软件包 | @webfer/mcp-ansible-drupal(npm) |
| 受影响版本 | 2.0.0 |
| 修复版本 | 2.0.3(发布于 2026-06-01) |
| CVSS v3.1 | AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 8.4 高危(stdio 传输)。若服务器被包装在网络传输中,AV:N → 9.8 严重。 |
| 报告者 | s1ko(github.com/s1ko,[email protected]) |
| CVE 分配日期 | 2026-07-13,MITRE CNA-LR |
此问题已修复。请升级至 2.0.3 或更高版本。
MCP 工具参数受攻击者影响。它们由 LLM 根据智能体处理的内容
——文档、网页、工具输出——生成,因此间接提示注入使攻击者能够控制
工具处理程序接收到的值。若处理程序将其中任何值传入 shell,
这种影响就会转化为在运行 MCP 服务器的
主机上执行代码。这与先例 aws-mcp-server / CVE-2026-5058 的模型相同。
其后果是,“调用方是受信任的 LLM”并不能作为缓解措施。 工具参数是不可信输入。
2.0.0 中的 src/helpers/runAnsible.ts 构建了一个参数数组,然后在启用 shell 的情况下
运行它:
const proc = spawn(ansibleCmd[0], ansibleCmd.slice(1), { shell: true });
在 shell: true 的情况下,Node 不会以 ansibleCmd[0] 作为可执行文件、其余元素作为 argv 来执行。它会把整个数组拼接成一个字符串,然后交给 /bin/sh -c,且不会对数组元素进行任何引号包裹或转义。因此,任何包含 ;、&&、|、反引号或 $() 的元素都会突破原本预期的命令边界。
可被利用的路径是 executeDeployment MCP 工具(src/tools/executeDeployment.ts),它会把调用方提供的 extraVars 以 --extra-vars key=value 的形式转发到数组中。当值为 ; touch /tmp/marker ; 时,会产生:
/bin/sh -c "ansible-playbook -i inv.ini play.yml ... --extra-vars deploy_env=; touch /tmp/marker ; echo INJECTED"
同一版本中的第二个 sink 将 projectRoot 插值到
execSync('ansible-vault encrypt ' + vaultPath) 中。
poc/driver.mjs 直接使用精心构造的
extraVars 值调用 runAnsible,并检查标记文件。无需安装
ansible-playbook —— 无论前导二进制文件是否解析成功,注入的命令都会在同一个 /bin/sh -c
字符串中执行。
npm pack @webfer/[email protected] && tar xf webfer-mcp-ansible-drupal-2.0.0.tgz
node poc/driver.mjs
在受影响的版本上预期出现:
{"target":"@webfer/mcp-ansible-drupal 2.0.0","sink":"runAnsible -> spawn(cmd[0], cmd.slice(1), {shell:true})","vector":"executeDeployment extraVars value","marker":"/tmp/PWNED_ansible","created":true,"verdict":"CONFIRMED - command injection executed"}
已于 2026-06-01 在隔离容器中验证,并于 2026-06-13 使用一个无害的 touch 标记重新验证。仅对你获授权测试的基础设施运行它。
ansible-playbook 的 --extra-vars 值中包含 ;、&&、||、|、反引号或 $(。合法的 Ansible 变量值基本上从不会包含这些字符。sh -c 进程,其命令行包含 ansible-playbook 并且在分隔符之后还有第二条命令——这是一种进程树信号(auditd、eBPF、Falco、EDR),不依赖应用程序日志。ansible-playbook、git 和 ansible-vault 是预期内的;shell、解释器或网络客户端则不是。executeDeployment 参数包含 shell 元字符。记录工具参数——大多数 MCP 部署不会这样做,而这是从应用层面唯一能看到注入值的地方。MITRE ATT&CK T1059.004 Command and Scripting Interpreter: Unix Shell。
升级到 @webfer/mcp-ansible-drupal 2.0.3 或更高版本。 当前源代码调用 spawn(ansibleCmd[0], ansibleCmd.slice(1), { … }) 时没有 shell 选项,因此数组作为 argv 传递,元字符失去其含义。
MCP 工具处理程序的通用规则,以及此修复在此处的应用:
shell: true。数组形式的存在正是为了避免使用 shell。execFile/spawn。z.string() 只能证明该值是字符串,对其中包含什么毫无证明。在值集合已知时使用允许列表;在未知时拒绝 shell 元字符。NIST SP 800-53r5 SI-10;OWASP ASVS v4 §5.3.8;CWE-78 缓解措施 M1 和 M2。
| 日期 | 事件 |
|---|---|
| 2026-06-01 | 漏洞针对 2.0.0 动态验证 |
| 2026-06-01 | 2.0.3 发布到 npm,移除了 shell: true |
| 2026-06-13 | 在第二台主机上重新验证 |
| 2026-07-13 | MITRE CNA-LR 分配 CVE-2026-52618,s1ko 被记为发现者 |
| 2026-08-22 | 本文发布 |
aws-mcp-server)同一轮研究中的配套公告: CVE-2026-52616、 CVE-2026-52617。
MIT — 参见 LICENSE。