MCP 安全:在经历 95 次生产环境故障后的心得体会
我曾以为安全很简单。更新依赖。使用 HTTPS。不要硬编码密钥。
我错了。
在经历了 95 次生产环境故障和 1,800 小时的开发后,我意识到 Model Context Protocol (MCP) 的安全性与众不同。它不像标准的 REST API 安全。
MCP 带来了新的风险,因为客户端是 LLM,而不是人类。
以下是保护你的 MCP 服务器安全必须了解的内容。
1. MCP 威胁模型
在 REST 中,你确切地知道是谁在调用你的 API。而在 MCP 中,LLM 充当了中间人。这改变了一切:
- LLM 可能会幻觉出工具调用或参数。
- 用户不会直接调用工具。他们与 LLM 对话,然后由 LLM 与你的服务器对话。
- 恶意客户端可能会在发现(discovery)阶段探测你服务器中隐藏的工具。
你面临的最大威胁不仅仅是黑客。还可能是一个出于好意但犯了错、导致系统崩溃的 LLM。
2. API 密钥管理
许多开发者为了图方便,会将 API 密钥放在查询参数(query parameters)中。这是一个错误。查询参数会出现在每一个服务器日志和代理中。
请遵循以下规则:
- 使用 Header 身份验证(
Authorization: Bearer)。 - 避免在 JSON Body 中传递密钥。
- 为每个客户端签发不同的 API 密钥。这有助于你追踪使用情况,并在不影响整体运行的情况下撤销访问权限。
3. 严格的输入验证
LLM 会猜错。它们会发送错误的类型和额外的参数。你必须验证每一次调用:
- 首先检查工具名称是否存在于你的列表中。
- 拒绝带有额外参数的调用。不要只是忽略它们。
- 精确匹配参数类型。不要进行数据类型强制转换(coerce)。
- 为字符串和数组设置严格的大小限制,以防止内存崩溃。
- 清理(Sanitize)所有文件路径,以防止目录遍历攻击。
4. 分层速率限制
一个用户提示词(prompt)可能会同时触发十次工具调用。这可能在几秒钟内耗尽你的连接池。
使用三层防御:
- 基于 API 密钥的限制,用于控制客户端的使用量。
- 基于 IP 的限制,用于阻止暴力破解攻击。
- 并发连接限制,用于在突发流量期间保持服务器运行。
5. Prompt 注入风险
用户可以诱导 LLM 调用具有破坏性的工具。如果用户告诉 LLM 删除所有笔记,LLM 真的可能会这么做。
保护措施:
- 将读操作和写操作分离。
- 对于任何删除或更新操作,都需要用户手动确认。
- 为你的数据库用户遵循最小权限原则。
安全是一个持续的过程。从更好的密钥管理和严格的验证开始。这些步骤可以解决大部分问题。
Optional learning community: https://t.me/GyaanSetuAi
