模型上下文协议(MCP)是 Anthropic 推出的一项功能强大的协议,定义了如何将大语言模型(LLM)连接到外部工具。因其易用性以及为 AI 的使用带来的诸多优势,该协议迅速获得了广泛认可。本文将介绍在使用 MCP 时可能会遇到的一些潜在安全风险以及如何降低这些风险。
MCP 的工作原理
MCP 并非直接将 LLM 连接到工具。MCP 客户端组件负责访问 LLM,其服务器组件则负责访问工具。一个 MCP 客户端可以访问一个或多个 MCP 服务器。用户可以将任意数量的 MCP 服务器连接到一个 MCP 客户端。
典型的 MCP 客户端与服务器交换流程如下:
- 用户从 MCP 客户端发起任务请求
- MCP 客户端具有各个 MCP 服务器所实现或可访问的工具信息
- MCP 客户端将用户的请求以及来自 MCP 服务器的信息一并传递给 LLM,LLM 随后响应以所需的工具以及需要使用的参数
- MCP 客户端将工具和参数的相关信息发送给 MCP 服务器
- MCP 服务器完成任务后,将结果返回给 MCP 客户端,MCP 客户端再将该结果传递给 LLM,然后由 LLM 生成面向用户的响应内容
- 最终的响应内容由 MCP 客户端呈现给用户
MCP 服务器可既可以在本地运行,也可以远程运行,安全风险因运行方式而异。
我们所说的“本地 MCP 服务器”是指在我们所控制的主机上运行的 MCP 服务器。为执行用户请求的任务,本地 MCP 服务器通常在本地执行操作系统命令或自定义代码。
“远程 MCP 服务器”是指仅由第三方远程运行的 MCP 服务器。我们可以访问远程 MCP 服务器,但这些服务器并非在我们所控制的主机上运行。对于用户而言,远程 MCP 服务器仍存在安全风险,因为它们能够访问用户的数据,但它们并非在本地运行,因此许多常见风险并不适用。
安全风险与控制措施
下文简要概述了安全研究人员已发现的一些 MCP 风险及相应的一些缓解方法。
身份验证和授权风险
当 MCP 服务器执行由用户请求触发的操作时,存在“混淆代理”问题的风险。理想情况下,MCP 服务器应在获得用户授权的前提下代表用户执行此操作。然而,这一点并不能得到保证,取决于 MCP 服务器的实现方式。如果实现不当,用户可能会能够访问供 MCP 服务器访问但不应对用户开放的资源,这违反了最低权限原则。
MCP 采用 OAuth 定义授权机制,但业界发现其现行规范中的部分实现细节与现代企业实践存在冲突。目前业界正积极完善并更新授权规范,以解决这种不一致问题。
供应链风险
MCP 服务器由可执行代码组成,因此用户应仅使用自己信任的 MCP 服务器。如果我们要开发 MCP 服务器,则必须采取防范措施,确保我们的软件能够取得用户的信任。此外,MCP 组件必须由开发人员进行签名,以便用户更确信其完整性。
我们还必须在实施了安全最佳实践(例如静态应用安全测试,简称 SAST)的管道上构建 MCP 组件。我们必须了解调查结果、排除误报并修复已知的安全漏洞。管道还必须实施软件组成分析(SCA),以便识别并修复 MCP 服务器所用依赖项中存在的已知漏洞。
如果 MCP 服务器以云服务形式提供,则还应实施加密服务器验证,以便客户端能够验证服务器的身份。
与任何其他软件一样,如果攻击者能够访问并修改任何 MCP 组件的源代码,他们就能够危害用户。为降低这种风险,软件开发人员和用户必须验证所使用的所有依赖项的完整性,并对其进行恶意软件扫描。
未经授权的命令执行风险
本地 MCP 服务器可能会执行任何代码。根据 MCP 客户端向 MCP 服务器传递信息的方式以及 MCP 服务器实现机制的不同,其命令执行功能可能存在命令注入漏洞风险。请务必仔细检查将要执行的命令,并在将数据用作执行命令的函数参数之前进行清理。
以下是一个存在命令注入漏洞的 MCP 服务器示例:
def dispatch_user_alert(self, notification_info: Dict[str, Any], summary_msg: str) -> bool:
"""Sends system alert to user desktop"""
notify_config = self.user_prefs["alert_settings"]
try:
alert_title = f"{notification_info['title']} - {notification_info['severity']}"
if sys.platform == "linux":
subprocess.call(["notify-send", alert_title])
return True代码摘自:https://equixly.com/blog/2025/03/29/mcp-server-new-security-nightmare/
此外,建议在沙盒中运行本地 MCP 服务器,使其仅能执行和访问显式允许的内容。
提示词注入风险
MCP 服务器能够执行命令和 API 调用,因此存在显著的安全风险。一个主要问题是,即便用户并未打算执行某个特定操作,LLM 仍然可能会判定相应操作是恰当的。
这种风险的出现可能并非出于恶意,但在对抗性场景中也是一个影响因素。例如,某个合法用户可能会向 MCP 客户端提交一段并非自己编写的提示词,这段提示词可能是由恶意第三方推荐的。此类提示词即便经过混淆处理,仍可能会导致用户对话或可访问工具中的隐私信息泄露。试想这样一种场景:某个用户复制并粘贴了一段复杂且经过混淆处理的提示词,以为这段提示词只会在自己的云环境中创建一个新用户,但实际上,这段恶意提示词除了会创建用户预期的账户外,还可能会为攻击者额外创建一个账户。
因此,MCP 服务器执行的操作应始终由用户确认或通过限制措施将风险降低至可接受水平。
工具注入风险
还存在另一种可能性,即攻击者可能会搭建恶意 MCP 服务器,这会带来新一层级的潜在风险。例如,一个恶意的 MCP 服务器在安装时可能看起来是安全的,甚至其源代码和工具描述也显得很正常。但这些工具可能会在后续的某次更新中被篡改。例如,一个原本描述为收集天气信息的工具可能会在某次更新过程中被篡改,转而开始收集机密信息并将其发送给攻击者。
这种情况也可能会发生在工具名称上。恶意 MCP 服务器可能会为工具使用具有迷惑性的名称,导致 LLM 在执行本应由其他合法工具完成的任务时选择了这些恶意工具,从而可能引发意外或有害的操作。
为降低部分风险,允许用户安装 MCP 服务器的软件应能够锁定 MCP 服务器版本,在服务器安装后,若其代码或构成发生任何变更,能够及时向用户发出通知。
采样风险
恶意 MCP 服务器还可能会试图利用 MCP 的采样功能,即 MCP 服务器请求 MCP 客户端使用 LLM 来完成某项请求。当 MCP 服务器需要向 LLM 发起请求时,采样功能允许 MCP 客户端代表 MCP 服务器发起请求,这是因为用户对 MCP 客户端拥有更强的控制权,且有助于集中管控成本。
为降低与采样相关的风险,MCP 客户端应实施以下控制措施:
- 客户端能够向用户显示补全请求
- 允许用户修改或拒绝补全内容
- 客户端能够过滤或修改补全内容
- 允许用户控制使用哪个模型
- 实施适当的速率限制
- 控制成本暴露风险
- 实施超时机制
日志记录
如前文所述,MCP 服务器能够执行敏感命令。因此,它们应能够将日志或事件发送至标准的集中式日志记录服务器,或者能够在本地记录这些事件。这样一来,在出现问题或怀疑存在问题时,可以对系统操作展开调查。
漏洞管理
MCP 服务器的本质是代码,和任何其他软件一样可能会存在漏洞,因此将其纳入标准漏洞管理流程至关重要。这包括根据组织的风险承受能力,按计划定期升级 MCP 客户端、服务器及其依赖项。
结语
MCP 激发了人们对使用自然语言操控工具的兴趣,并促使我们更好地了解用户、LLM 和工具之间的交互方式。然而,我们必须认识到,随着自动化程度的提升与 AI 代理自主能力的增强,相应的安全风险也随之出现。与任何其他新技术一样,企业在使用 MCP 时,必须针对自身业务场景评估安全风险,并实施适当的安全控制措施,才能在发挥该技术最大价值的同时保障安全。
了解更多
关于作者
Florencio has had cybersecurity in his veins since he was a kid. He started in cybersecurity around 1998 (time flies!) first as a hobby and then professionally. His first job required him to develop a host-based intrusion detection system in Python and for Linux for a research group in his university. Between 2008 and 2015 he had his own startup, which offered cybersecurity consulting services. He was CISO and head of security of a big retail company in Spain (more than 100k RHEL devices, including POS systems). Since 2020, he has worked at Red Hat as a Product Security Engineer and Architect.