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

MCP配置注入:一份mcp.json如何变成RCE攻击入口

发布时间:2026/9/25 9:08:22

资讯中心
01
ARTICLE

MCP配置注入:一份mcp.json如何变成RCE攻击入口

MCP配置注入:一份mcp.json如何变成RCE攻击入口
1. 从一个 mcp.json 文件说起为什么配置文件能变成攻击入口很多人第一次接触 MCPModel Context Protocol是在给编辑器或 Agent 工具接一个本地能力服务的时候。流程通常很简单在项目根目录或者用户配置目录里放一个mcp.json里面写清楚要启动哪个命令、传什么参数、设什么环境变量然后重启客户端工具列表里就多出几个能调用的函数。整个过程顺滑得让人放松警惕因为大家潜意识里觉得这不过是个配置文件。问题恰恰出在这个不过是个配置文件的认知上。mcp.json里有一个字段叫command还有一个字段叫args。当客户端读取这份配置时它会用command指定的可执行程序拼接args里的参数然后以子进程的方式把它拉起来。这个行为在 MCP 的 stdio 传输模式下是标准动作——客户端和服务端通过标准输入输出通信服务端就是一个被拉起的本地进程。换句话说一份 mcp.json 本质上等价于一条本机命令执行指令。你写什么它就跑什么。这就是标题里一份 mcp.json 就是一次 RCE的字面含义。RCE 是 Remote Code Execution远程代码执行的缩写在安全语境里指的是攻击者能够在你机器上执行任意代码。而 MCP stdio 配置注入的核心逻辑是只要攻击者能影响你mcp.json的内容他就能让客户端替他执行命令。这个影响的途径比想象中多得多——可能是一个恶意仓库自带的配置文件可能是一个被投毒的 MCP Server 安装脚本也可能是一段看起来人畜无害的文档里让你复制粘贴这段配置。我写这篇东西的出发点很直接过去一段时间里MCP 生态爆发式增长各种 Server 层出不穷从浏览器控制、数据库查询到设计稿读取几乎每个工具都在教你往 mcp.json 里加一段。但很少有人系统性地讲清楚这段配置背后到底发生了什么以及哪些写法会把你自己送走。下面我会把五条真实可复现的攻击链拆开讲再给一份能直接落地的加固清单。适合所有正在用 MCP、准备接 MCP Server、或者负责团队工具链安全的人看。不需要你是安全专家但需要你愿意认真对待一个 JSON 文件。2. MCP stdio 的工作机制命令是怎么被拉起来的2.1 stdio 传输模式的进程模型要理解攻击链先得把 stdio 模式的进程模型讲透。MCP 定义了多种传输方式stdio 是最基础也最常用的一种。它的工作方式是这样的客户端比如某个 AI 编辑器、Agent 框架读取配置拿到command和args通过操作系统的进程创建接口在类 Unix 系统上是forkexec系列在 Windows 上是CreateProcess启动一个子进程。这个子进程的标准输入和标准输出被客户端接管双方用 JSON-RPC 格式的消息在管道里来回通信。关键点在于客户端并不校验command指向的程序是不是合法的 MCP Server。它只是忠实地执行配置里写的命令。你写npx some-mcp-server它就去找 npx 然后跑你写python evil.py它就去跑 Python 脚本你写bash -c ...它就把那串东西交给 bash。客户端在这里扮演的是一个无脑执行器的角色信任完全建立在配置文件本身的可信度上。这个设计本身不算缺陷因为配置文件理应由用户自己掌控。但现实是配置文件的来源往往不受用户掌控。这就引出了后面所有的攻击面。2.2 command、args、env 三个字段的真实语义很多人对这三个字段的理解停留在表面我逐个拆一下。command是要执行的程序路径或名称。如果是不带路径的名称系统会走PATH环境变量查找。这意味着攻击者可以利用 PATH 劫持——如果他能往 PATH 里靠前的目录放一个同名程序你的配置就会跑到他的程序上去。这个手法在本地提权和供应链攻击里非常经典。args是参数数组。注意它是数组不是字符串所以正常情况下每个元素会被当作独立参数传递不会经过 shell 解析。这一点很重要如果客户端实现规范args里的内容不会被 shell 解释那么; rm -rf /这种注入是无效的。但问题在于很多客户端的实现并不规范或者某些 Server 的启动方式本身就要求经过 shell。一旦经过 shellargs里的元字符就会生效注入面瞬间打开。env是环境变量。这个字段经常被忽视但它同样危险。环境变量可以影响动态链接器的行为比如LD_PRELOAD、DYLD_INSERT_LIBRARIES可以覆盖程序查找路径PATH、PYTHONPATH、NODE_OPTIONS还可以传递各种凭据。一个被污染的env字段不需要改command就能实现代码执行。2.3 客户端信任边界在哪里断裂把上面几点串起来信任边界的问题就清楚了。理想情况下信任边界应该画在用户亲手写的配置和外部输入之间。但实际使用中这条边界被反复跨越你从 GitHub clone 了一个项目项目里带了.mcp.json你的编辑器自动读取了它。你按照某个教程复制了一段配置没仔细看command后面跟的是什么。你安装了一个 MCP Server 包它的安装脚本顺手改了你的全局配置。你的配置文件放在一个被云同步、被其他工具读写的目录里。每一条都是信任边界断裂的实例。而断裂之后从配置被污染到命令被执行之间几乎没有缓冲。3. 五条真实攻击链的完整拆解这一节是全文的核心。我把五条攻击链按利用难度从低到高、隐蔽性从弱到强排列每条都给出触发条件、执行路径和可观测的痕迹。需要说明的是这些链条的描述目的是防御所有细节都停留在原理层面不提供可直接武器化的完整载荷。3.1 攻击链一仓库自带配置文件的自动加载这是门槛最低的一条。很多 AI 编辑器和 Agent 工具支持项目级配置也就是在项目根目录放一个.mcp.json或类似名字的文件打开项目时自动加载。攻击者只需要在一个看起来正常的开源项目里塞进这样一份配置内容大致是让command指向一个项目内的脚本args传几个参数。受害者 clone 项目、用编辑器打开配置被自动读取脚本被执行。整个过程没有任何弹窗确认。脚本可以做得非常克制——先只做一件事把当前环境信息回传或者写一个标记文件。等你发现的时候可能已经过去很久了。这条链的关键在于自动加载这个行为。手动加载的配置至少给了用户一次我要不要加的决策机会自动加载把这个机会抹掉了。我个人的习惯是任何会自动读取项目内配置的工具我都会先去设置里把自动加载关掉改成手动确认。3.2 攻击链二npx 与 uvx 的包名混淆第二条链利用的是包管理器的动态解析特性。很多 MCP Server 的推荐配置长这样command是npxargs是[-y, some-mcp-server]。这里的some-mcp-server是一个包名npx 会去 npm registry 上找这个包并执行。攻击面在于包名。如果这个包名没有被原作者注册或者存在拼写相近的包比如把figma-mcp写成figma-mcp-server、figma_mcp攻击者可以抢注一个同名或近似名的包里面放上恶意代码。用户复制配置的时候不会去核对包的真实来源npx 一跑恶意包就执行了。uvxPython 生态的类似工具面临同样的问题。更麻烦的是npx -y和uvx默认会跳过确认直接安装执行连这个包你没装过确定要装吗的提示都没有。我见过太多配置里直接写npx -y xxx这个-y就是省掉确认的开关方便是方便风险也是实打实的。防御这条链的办法很朴素配置里尽量用完整路径或已锁定的本地安装不要依赖运行时的动态包解析。如果非要用 npx至少把包名核对到官方仓库的确切地址并且考虑用--package指定版本。3.3 攻击链三env 字段里的动态链接器注入第三条链更隐蔽因为它不改command只改env。前面提过环境变量能影响动态链接器的行为。在 Linux 上LD_PRELOAD可以让程序在启动时优先加载指定的共享库在 macOS 上对应的机制是DYLD_INSERT_LIBRARIES。攻击者只要在env里加上这么一条指向一个他控制的.so或.dylib文件那么被拉起的 MCP Server 进程在启动瞬间就会执行他的代码。这条链的可怕之处在于command看起来完全正常——就是一个普通的 MCP Server 启动命令用户扫一眼根本不会起疑。危险藏在env里那一行不起眼的变量。而且这种注入发生在进程初始化的极早期很多应用层的日志和监控根本来不及记录。防御上我建议对env字段采取白名单策略。只允许传递 Server 明确需要的变量比如 API Key、数据库连接串这类业务凭据绝不允许出现LD_、DYLD_、PYTHONPATH、NODE_OPTIONS这类能影响运行时行为的变量。如果某个 Server 的文档要求你设置这些那本身就是一个危险信号值得重新评估要不要用它。3.4 攻击链四shell 包装导致的参数注入第四条链针对的是那些必须经过 shell 才能启动的场景。有些 MCP Server 的启动命令比较复杂需要管道、重定向或者条件判断配置里就会写成command: bash、args: [-c, some command with $VARIABLE]这种形式。一旦经过 shellargs里的内容就会被 shell 解析注入面彻底打开。具体来说如果args里拼接了任何来自外部的、未经过滤的字符串——比如从环境变量读来的路径、从配置文件读来的参数——攻击者就可以通过控制这个字符串来注入 shell 元字符。一个分号、一个反引号、一个$()就能在原本的命令后面追加一条完全不同的命令。这条链的触发条件比前几条苛刻一些需要配置里存在外部可控字符串进入 shell 命令的模式。但在实际项目里这种模式并不罕见尤其是那些为了灵活而把路径、参数做成可配置的 Server。防御原则很简单能不用 shell 就不用 shell。如果非用不可所有进入 shell 的变量都必须经过严格转义或者改用参数数组的形式传递。3.5 攻击链五配置同步与共享带来的横向扩散最后一条链不针对单台机器而是针对配置的传播。很多人会把mcp.json放在云盘同步目录、团队共享仓库、或者 dotfiles 管理工具里。这本身是好习惯方便多设备一致。但一旦这份配置被污染污染就会随着同步扩散到所有设备。更隐蔽的是团队场景。一个团队共用一份 MCP 配置模板某天有人在模板里加了一个方便大家的 Server其他人拉取更新后自动生效。如果这个 Server 是恶意的或者它的启动命令被篡改过整个团队在同一时间被拿下。这种横向扩散的杀伤力远大于单点攻击。防御这条链需要从流程入手配置文件纳入版本控制时要有 review 机制任何对command、args、env的改动都要有人工确认云同步目录里的配置文件要定期审计团队模板要有明确的维护者和变更记录。4. 从配置到执行攻击者视角的完整链路复盘把五条链放在一起看会发现它们共享一个三段式结构污染入口 → 解析放大 → 执行落地。理解这个结构比记住五条链本身更重要因为新的攻击手法大概率还是这个骨架的变体。污染入口是攻击者接触配置文件的途径。可能是仓库、可能是包名、可能是文档、可能是同步渠道。这一段的防御核心是控制配置来源只从可信渠道获取配置对任何自动加载保持警惕。解析放大是配置文件被客户端解读的过程。不同的客户端实现差异很大有的严格按数组传参有的会经过 shell有的会自动展开变量有的会合并多份配置。这些差异决定了同样的配置在不同客户端上的实际行为可能完全不同。这一段的防御核心是了解你用的客户端到底怎么解析配置不要假设它和别的客户端一样。执行落地是命令真正跑起来的那一刻。到了这一步防御手段已经很有限了主要靠运行时的沙箱、权限隔离和监控。所以真正有效的防御必须前移在污染入口和解析放大阶段就把问题拦住。我自己的做法是给 MCP Server 单独建一个低权限的系统账户所有 Server 都以这个账户运行能访问的文件和网络都受限。这样即使某条链被触发攻击者拿到的也只是一个受限环境而不是我的整个工作账户。这个隔离成本不高但收益很大。5. 加固清单从配置写法到运行时隔离下面这份清单是我在实际使用中逐步积累的按配置层 → 客户端层 → 运行时层三层组织。每一条都对应前面讲过的具体风险不是泛泛而谈。5.1 配置层的写法规范风险点危险写法推荐写法命令来源npx -y some-package本地已安装的完整路径或锁定版本的调用参数传递bash -c cmd $VAR参数数组避免 shell 解析环境变量传入LD_PRELOAD、NODE_OPTIONS白名单只传业务必需的凭据路径引用相对路径、依赖 PATH 查找绝对路径明确指向可信位置配置来源自动加载项目内配置手动确认或只加载用户级配置配置层的第一原则是显式优于隐式。所有能让客户端自己猜的地方都改成明确写死。包名写全、路径写绝对、版本写死、变量列全。多打几个字换来的确定性是值得的。第二原则是最小权限。配置里只放这个 Server 跑起来必需的东西多余的变量、多余的参数一律不加。很多注入链之所以能成立就是因为配置里存在本来不需要但顺手加上了的字段。5.2 客户端层的加载策略客户端的选择和配置同样重要。我在选工具时会重点看几个点它是否支持项目级配置的自动加载自动加载能不能关加载配置时有没有确认提示对command和env有没有基本的校验如果某个工具默认自动加载项目内配置且无法关闭我会非常谨慎地使用它或者干脆把它跑在隔离环境里。如果它加载配置时连个提示都没有那这个工具的安全模型基本等于没有。还有一个容易被忽视的点配置的合并顺序。有些客户端会同时读取用户级配置和项目级配置然后合并。如果合并逻辑是项目级覆盖用户级那么一个恶意项目就能覆盖你精心设置的安全配置。了解你所用客户端的合并规则必要时把项目级配置的加载关掉。5.3 运行时层的隔离与监控到了运行时层目标不再是阻止执行而是限制执行的影响范围和留下可追溯的痕迹。隔离方面我推荐至少做到三点用独立的低权限账户运行 MCP Server用容器或沙箱限制文件系统和网络访问对敏感目录设置明确的拒绝规则。这三点不需要多复杂的工具系统自带的账户管理和权限控制就能做到大部分。监控方面重点是记录哪个配置启动了哪个进程。很多系统层面的进程审计工具可以做到这一点把 MCP Server 的启动事件单独标记出来定期 review。一旦发现某个 Server 的启动命令和配置里写的不一致或者启动了配置里没写的子进程就是一个明确的告警信号。提示不要等到出事才去翻配置。养成定期审计mcp.json的习惯尤其是command、args、env三个字段。任何一次改动都值得你花两分钟确认。6. 几个我踩过的坑和常见误区讲完方法论说几个具体的坑。这些都是我自己或者身边人真实遇到过的写出来希望能帮你省点事。第一个坑是以为 JSON 格式合法就安全。JSON 只是语法语法正确不代表内容安全。一份格式完美、缩进整齐的mcp.json完全可以是恶意的。不要用看起来很正常来判断配置的安全性要看字段的实际语义。第二个坑是忽视env字段。我早期审配置只看command和args觉得env就是传个 API Key 而已。直到有一次看到一份配置在env里塞了NODE_OPTIONS--require ./hook.js才意识到这个字段的威力。现在我看配置env是第一个看的。第三个坑是盲目复制教程里的配置。网上很多 MCP 教程为了让你快速跑通直接给一段配置让你粘贴。这些配置里的包名、路径、参数往往没有经过安全审视。复制之前至少把command指向的程序搞清楚是什么args里的每个参数是什么意思。第四个坑是把 MCP Server 当成普通依赖。普通依赖出问题影响的是构建产物MCP Server 出问题影响的是你的运行环境因为它是在你机器上以你的权限跑起来的进程。这个区别决定了 MCP Server 需要比普通依赖更严格的准入。第五个坑是以为隔离了网络就安全。有些攻击链根本不需要网络本地文件读写、本地命令执行就够了。网络隔离能挡住数据外传但挡不住本地破坏。隔离要全面不能只做一半。7. 关于 MCP 生态安全的一点个人判断MCP 这个协议本身设计得不算差stdio 模式的选择也有它的合理性——简单、通用、跨平台。问题不在协议而在生态的成熟度。现在的 MCP 生态有点像早期的 npm包数量爆发式增长但准入、审计、签名这些基础设施还没跟上。在这个阶段安全责任很大程度上落在使用者自己身上。我的判断是接下来一段时间里MCP 配置注入类的问题会越来越多因为攻击成本低、收益明确、防御意识普遍不足。等到生态成熟、工具链内置了足够的防护这类问题才会慢慢减少。在那之前把mcp.json当成一份会被执行的代码来对待是最实际的自我保护。具体到操作上我给自己定了几条硬规矩任何新加的 MCP Server先在一个隔离环境里跑一遍观察它启动了什么进程、访问了什么文件、连了什么地址确认没问题再进主环境。任何对现有配置的改动都走一次人工 review哪怕只是改个参数。任何来自外部的配置片段先拆开看字段再决定要不要用。这些规矩听起来麻烦但比起某天发现自己的机器被一份 JSON 文件拿下的代价这点麻烦实在不算什么。配置文件从来都不只是配置它是你交给工具的一份信任契约。契约的条款值得你逐字读一遍。
02
RELATED NEWS

相关资讯

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

03
WHY YAOTU

想打造同款高转化官网?

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

◈

场景化定制

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

◐

营销型架构

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

▲

全周期服务

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

免费获取你的建站方案

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