窃取MCP服务器存储的长期凭证
作为我们MCP安全系列第四篇文章,本文研究的漏洞不同于之前讨论的协议层缺陷:许多MCP环境将第三方服务的长期API密钥以明文形式存储在本地文件系统,且常配置不安全的全局可读权限。该漏洞影响所有连接到LLM应用的系统,MCP环境功能越强大,不安全存储凭证的风险就越高。
这一现象在MCP生态中极为普遍。我们在多个工具中观察到该问题,从连接GitLab、Postgres和Google Maps的官方服务器,到Figma连接器和Superargs包装器等第三方工具。攻击者只需利用文件泄露漏洞即可窃取API密钥,进而完全控制第三方服务中的数据。常见攻击方式包括:
- 本地恶意软件:用户级恶意程序通过扫描固定路径(如~/Library/Application Support/、~/.config/或应用日志)窃取凭证
- 其他漏洞利用:利用同一系统上其他软件的任意文件读取漏洞获取明文凭证
- 多用户系统:在共享工作站或服务器上,其他用户可直接读取全局可读文件中的凭证
- 云备份:自动备份工具可能将服务器配置文件同步到云存储,因配置不当导致凭证暴露
凭证窃取路径分析
路径1:不安全的配置文件
多数MCP服务器通过命令行参数或环境变量获取凭证,这些参数通常源自宿主AI应用管理的配置文件。我们在Google Maps、Postgres和GitLab的官方MCP服务器中均发现该模式。
以Claude Desktop为例,其在用户主目录创建claude_desktop_config.json
文件,在macOS上该文件具有全局可读权限:
$ ls -la ~/Library/Application\ Support/Claude\ Desktop/claude_desktop_config.json
-rw-r--r-- 1 user staff 2048 Apr 12 10:45 claude_desktop_config.json
路径2:聊天日志泄露凭证
另一种常见模式是用户直接将凭证输入AI聊天界面,依赖模型将其传递给MCP服务器。Supercorp的Superargs包装器就明确支持这种模式。
该方法存在双重风险:恶意MCP服务器可直接从对话历史窃取凭证;宿主AI应用通常会将完整对话历史(含嵌入凭证)记录到本地日志文件。例如Cursor和Windsurf应用将对话日志存储为全局可读文件:
$ ls -la ~/.cursor/logs/conversations/
-rw-r--r-- 1 user staff 15482 Apr 15 12:23 conversation_20240415.json
风险叠加案例:Figma连接器
某些实现会同时暴露两种攻击路径。社区提供的Figma MCP服务器允许用户通过工具调用设置API令牌,但随后会使用Node.js的fs.writeFileSync
函数将凭证保存到用户主目录的配置文件中。该函数默认创建权限为0666(-rw-rw-rw-)的文件,使得存储的Figma令牌全局可读(根据用户umask设置可能还可写)。
安全凭证管理方案
改进凭证存储方式需要多方协作:
- 第三方服务应增加OAuth支持,包括窄范围短期令牌
- MCP开发者应优先使用操作系统提供的凭证存储API(如Windows凭据管理API和macOS钥匙串)
- 终端用户应审慎选择软件,或手动收紧AI软件遗留敏感文件的权限
随着MCP逐渐成为强大AI系统的基础框架,我们必须扭转"安全后置"的开发模式,从设计之初就将安全凭证处理作为最高优先级。