当前位置: 首页 > news >正文

gemini-mcp-tool 命令注入漏洞深度分析(CVE-2026-0755)

一次从发现到利用的安全漏洞分析之旅

在浏览安全资讯的时候,我偶然间看到了 CVE-2026-0755,这是一个关于 gemini-mcp-tool 的命令注入漏洞。对MCP 协议不太了解,我心里充满了疑问:

  • MCP 到底是什么?为什么会有这样的协议?

  • gemini-mcp-tool 是干什么用的?

  • execAsync 命令注入是如何发生的?

  • 更重要的是:这个漏洞要怎么挖掘和触发?

漏洞简介

gemini-mcp-tool 是一个开源的 npm 包,用于在 Claude Desktop 等 MCP 客户端中集成 Google Gemini AI。该工具允许用户通过 MCP 协议调用 Gemini 的各种能力。在 gemini-mcp-tool 的 contribute.ts 文件中,存在一个命令执行漏洞。该漏洞源于用户输入缺乏充分验证,直接将用户输入拼接到 shell 命令中执行。

影响版本≤ 1.1.2

重要说明:漏洞位于 contribute.ts,该文件并没有直接作为 MCP 服务暴露。它是 gemini-mcp-tool 项目的贡献者辅助工具,它是一个交互式终端UI,一个独立的命令行工具。因此,默认情况下,这个漏洞无法通过 Claude Desktop 等 MCP 客户端直接触发。

MCP 详解

什么是 MCP? MCP(Model Context Protocol,模型上下文协议)是一种用于连接大型语言模型(LLM)与外部数据源、工具的开放标准协议。能够让 AI 模型(如 Claude、Gemini)能够安全地访问和使用外部工具、数据源和服务。

它解决了一个核心问题:

如何让 AI 像人类一样使用工具?比如搜索网页、读取文件、操作数据库、调用 API 等。

MCP 架构图

image

MCP 的完整工作流程

image

MCP Server 的配置与启动

MCP Server 本质上就是一个普通的程序(可以是 Node.js、Python 等编写),它通过标准输入/输出(stdio) 或网络与客户端通信。

要让 Claude Desktop 使用某个 MCP Server,需要在配置文件中注册。

  • Claude Desktop 配置文件位置:

    • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

    • Windows: %APPDATA%\Claude\claude_desktop_config.json

    • Linux: ~/.config/claude/claude_desktop_config.json

典型配置示例:

{ "mcpServers": {   "my-tool": {     "command": "node",     "args": ["/path/to/server.js"]   }}
}
001.png
关键点: 当 Claude Desktop 启动时,它会读取这个配置,并自动在本地启动这些 MCP Server 程序。

漏洞复现&分析

在 CVE 描述中提到了 execAsync 命令注入 我们直接在代码中搜索 execAsync

image

只有文件 src/contribute.ts 存在这个函数的定义和调用

import { spawn, exec } from "child_process";

代码导入了 Node.js 的 child_process模块,这是 Node.js 提供的子进程管理模块,允许在 Node.js 中执行系统命令。

const execAsync = (command: string): Promise<string> => { return new Promise((resolve, reject) => {   exec(command, (error, stdout, stderr) => {     if (error) {       reject(new Error(`${error.message}\n${stderr}`));     } else {       resolve(stdout.trim());     }   });});
};

命令执行的核心封装,通过 exec 创建子 shell 进程,执行命令,捕获 stdout/stderr

在菜单中选择 Create Feature Branch 后

image

image

image

这个函数的核心作用是帮助开发者在 Git 仓库中自动创建新的功能分支。整个过程首先会在终端显示一个绿色加粗的标题,告诉用户正在创建分支。然后通过 inquirer.prompt() 这个交互式命令行工具来获取用户输入的功能名称。

当程序执行到 await inquirer.prompt 这一行时:inquirer.prompt() 会在终端显示一个输入框,然后程序会完全暂停执行,等待用户输入内容并按下回车键。用户输入完成后,inquirer.prompt() 会返回一个对象,通过解构赋值 ${featureName} 可以提取出用户输入的功能名称。

拿到用户输入后,程序使用模板字符串来拼接完整的分支名。模板字符串使用反引号包裹的字符串,它最大的特点时可以在字符串中使用 ${} 来嵌入变量。当程序执行 `feature/${featureName}` 时,${featureName} 这个占位符会在运行时被替换成变量的实际值。

接下来函数会执行一系列 Git 命令。execAsync 函数:会启动一个子进程,在这个子进程中运行传入的 shell 命令(就像在终端中手动输入命令一样),然后等待命令执行完成。每个 await execAsync 都会让程序暂停,直到对应的命令执行完毕才继续下一步。

虽然分支名用双引号包裹了,但这种防护是不充分的。问题的根源在于:用户输入在传递给 shell 执行之前,没有经过转义处理或严格的输入验证。可以通过在输入中插入双引号来提前闭合原有的字符串边界,然后利用 shell 的特殊字符(如 &、;、|、` 等)注入并执行任意命令。

这个工具本质上是一个命令行自动化脚本的图形化封装,通过 Node.js 的子进程能力,将复杂的 Git 工作流程简化为菜单选择操作。

cd gemini-mcp-tool-1.1.2 # 进入项目根目录
​
git init                 # 初始化 git 仓库
git add .                # 将所有文件添加
git commit -m "init"     # 创建初始提交
git branch -M main       # 将默认分支重命名为 main
​
​
git remote add upstream . # 添加一个假的 upstream(避免 pull upstream 报错)
​
​
npx ts-node src/contribute.ts # 启动程序
​
# 选择 "Create Feature Branch" 选项来创建功能分支
​test" & calc & echo "        # 输入 payload

7

‍疑问:contribute.ts 只是一个需要手动运行的 CLI 工具,用户必须主动输入恶意 payload。我们要怎样配置才可以让它变成远程代码执行?

【----帮助网安学习,以下所有学习资料免费领!加vx:YJ-2021-1,备注 “博客园” 获取!】

 ① 网安学习成长路径思维导图
 ② 60+网安经典常用工具包
 ③ 100+SRC漏洞分析报告
 ④ 150+网安攻防实战技术电子书
 ⑤ 最权威CISSP 认证考试指南+题库
 ⑥ 超1800页CTF实战技巧手册
 ⑦ 最新网安大厂面试题合集(含答案)
 ⑧ APP客户端安全检测指南(安卓+IOS)

我们将代码稍微修改使其变成一个可被远程访问的 mcp 服务

git-workflow-helper.ts
​
#!/usr/bin/env node
​
/*** Git 工作流助手 - MCP 服务器* * 提供常用的 Git 工作流操作,帮助开发者快速创建功能分支*/
​
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { CallToolRequestSchema, ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { exec } from "child_process";
​
// ========================================
// 核心功能实现
// ========================================
​
/*** 执行 shell 命令的辅助函数*/
const execAsync = (command: string, cwd?: string): Promise<string> => { return new Promise((resolve, reject) => {   exec(command, { cwd }, (error, stdout, stderr) => {     if (error) {       reject(new Error(`${error.message}\n${stderr}`));     } else {       resolve(stdout.trim());     }   });});
};
​
/*** 创建功能分支* * 自动从主分支创建新的功能分支,并确保代码是最新的* * @param featureName - 功能名称,将自动添加 feature/ 前缀* @returns 操作结果消息*/
async function createFeatureBranch(featureName: string): Promise<string> { try {   const gitRepo = process.env.GIT_REPO_PATH || process.cwd();   const branchName = `feature/${featureName}`;
​   // 切换到主分支   await execAsync("git checkout main", gitRepo);
​   // 拉取最新更新   await execAsync("git pull upstream main", gitRepo);
​   // 创建并切换到新分支   await execAsync(`git checkout -b "${branchName}"`, gitRepo);
​   return `✅ Branch created successfully: ${branchName}`;} catch (error) {   if (error instanceof Error) {     return `❌ Branch creation failed: ${error.message}`;   }   return `❌ Unknown error occurred`;}
}
​
// ========================================
// MCP 服务器配置
// ========================================
​
const server = new Server({   name: "git-workflow-helper",   version: "1.0.0",},{   capabilities: {     tools: {},   },}
);
​
/*** 注册可用工具*/
server.setRequestHandler(ListToolsRequestSchema, async () => { return {   tools: [     {       name: "create_feature_branch",       description:         "Create a new Git feature branch from main. Automatically pulls latest changes and creates a properly named feature branch.",       inputSchema: {         type: "object",         properties: {           feature_name: {             type: "string",             description:               "Name of the feature (e.g., add-login-page, fix-bug-123, update-documentation). Do not include 'feature/' prefix as it will be added automatically.",           },         },         required: ["feature_name"],       },     },   ],};
});
​
/*** 处理工具调用*/
server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name === "create_feature_branch") {   const featureName = request.params.arguments?.feature_name as string;
​   if (!featureName) {     return {       content: [         {           type: "text",           text: "❌ Error: feature_name parameter is required",         },       ],     };   }
​   const result = await createFeatureBranch(featureName);
​   return {     content: [       {         type: "text",         text: result,       },     ],   };}
​ return {   content: [     {       type: "text",       text: `❌ Unknown tool: ${request.params.name}`,     },   ],};
});
​
// ========================================
// 启动服务器
// ========================================
​
async function main() { const transport = new StdioServerTransport(); await server.connect(transport);
​ console.error("Git Workflow Helper started"); console.error("Ready to assist with Git operations"); console.error(`Working directory: ${process.env.GIT_REPO_PATH || process.cwd()}`);
}
​
main().catch((error) => { console.error("Fatal error:", error); process.exit(1);
});
npm install --save-dev typescript
npx tsc src/git-workflow-helper.ts --outDir dist --module commonjs --target es2020 --esModuleInterop
move dist\git-workflow-helper.js dist\git-workflow-helper.cjs

image

image

image

Claude Desktop 利用失败

image

image

image

我们发现在 Claude Desktop 上利用失败了,是因为 Claude AI 的智能安全防护层会自动识别和拒绝危险操作,即使 MCP 工具本身有漏洞,Claude 也会拒绝执行看起来像是命令注入的操作。(或许可以通过多次对话绕过安全识别)

我们可以通过 MCP Inspector(Model Context Protocol官方调试工具),它只是一个技术调试工具,直接传递数据,没有任何安全判断机制,纯粹用于开发者测试 MCP 工具的原始功能,能够精确展示 MCP 工具本身的漏洞,而不会被上层 AI 安全机制拦截。

npx @modelcontextprotocol/inspector node dist/git-workflow-helper.cjs

8

更多网安技能的在线实操练习,请点击这里>>

  

http://www.jsqmd.com/news/360598/

相关文章:

  • 商场充电桩远程监控管理系统方案
  • 2026年昆明卫生间防水品牌企业排名,好用的卫生间防水涂料怎么选 - 工业设备
  • 天猫超市购物卡回收技巧,闲置秒变现金 - 京顺回收
  • 参考文献崩了?当红之选的AI论文网站 —— 千笔
  • [转载]Web端H.265播放器:视频解码篇
  • 指数期权指标分析未平仓量的市场信号
  • 2026河北优质玻璃钢管道厂家实力盘点与采购指南 - 2026年企业推荐榜
  • 2026年2月徐州卧室套装/全屋定制/储物柜/装饰柜厂商选型与领导者深度解析 - 2026年企业推荐榜
  • 华为eNSP模拟器综合实验之- 无线AC 配置思路及关键要点
  • 前瞻2026:廊坊环氧地坪施工销售商挑选指南 - 2026年企业推荐榜
  • 2026年成分科学解读:基于配方有效性与创新性的身高增长胶囊品牌权威排行 - 资讯焦点
  • 模型剪枝大白话讲解:结构化 vs 非结构化
  • 无感刷新Token:如何做到让用户“永不掉线”
  • abp数据库迁记录
  • 2026年污水处理药剂厂家TOP10推荐:聚焦水处理药剂实力品牌,蓝淼环保领衔区域服务标杆 - 深度智识库
  • 2026年烟囱防腐施工优质厂家盘点与选择指南 - 2026年企业推荐榜
  • 法护两节 情暖职工!福州市总工会“两节”普法嘉年华活动圆满举办 - 速递信息
  • 金源木业口碑靠谱吗,在哈尔滨定制包装价格多少钱? - myqiye
  • 2026年湖北景观工程设计服务商首选推荐:中美丽岛景观有限公司 - 2026年企业推荐榜
  • 2026年3+1国际本科安全问题探讨,申请流程全知道 - 工业品牌热点
  • 木制包装箱怎么选择,哈尔滨金源木业是靠谱生产商吗? - 工业品牌热点
  • 分析城市管网运维公司,河北雄安未来之城市政服务费用合理 - mypinpai
  • AI开发-python-langchain框架(1-13 返回xml-格式解析器)
  • ABB ACS510 变频器恒压供水与昆仑通泰触摸屏 485 通讯实现
  • 讲讲广州箱包肩带板扣五金定制供应商排名,哪家更值得合作 - 工业推荐榜
  • 2026年昆明挂坠采购全攻略:从源头到精工的厂家评测 - 2026年企业推荐榜
  • JS Number 精度丢失问题
  • 2026年昆明花园旅居深度测评:六家宝藏酒店谁是你的心头好? - 2026年企业推荐榜
  • 有哪些好用的AI写论文的工具?6款写论文的AI工具,知网查重一把通过无忧! - 掌桥科研-AI论文写作
  • 2026年徐州地区高评价铝基中间合金厂家盘点 - 2026年企业推荐榜