4、身份认证与授权:Token认证机制、OAuth 2.0集成、会话管理漏洞分析

身份认证和授权,说白了就是MCP协议里的「门禁系统」。你想想看,一个MCP服务器对外暴露了那么多工具和资源,要是谁都能随便调用,那不乱套了?我这些年挖过的漏洞里,至少有三分之一跟认证授权有关。今天咱们就好好聊聊这块。

4.1 Token认证机制:JWT的那些坑

MCP协议里最常见的认证方式就是Token认证,尤其是JWT(JSON Web Token)。嗯,这里要注意,JWT本身是个好东西,但用不好就是灾难。

核心要点:JWT的签名验证是安全基石,但很多人只验证了「有没有签名」,没验证「签名对不对」。

我在项目中遇到过这么个案例:某MCP服务器在解析JWT时,直接用了jwt.decode(token, verify=False)。你猜怎么着?攻击者随便伪造一个Token,里面写上{"role": "admin", "sub": "attacker"},就能直接调用管理员接口。这漏洞挖得我都不好意思上报。

正确的做法应该是这样:

# 错误示范 - 千万别这么写
import jwt
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
payload = jwt.decode(token, verify=False)  # 危险!

# 正确做法
import jwt
from cryptography.hazmat.primitives import serialization

# 加载公钥
with open("public_key.pem", "rb") as f:
    public_key = serialization.load_pem_public_key(f.read())

try:
    payload = jwt.decode(
        token, 
        public_key, 
        algorithms=["RS256"],
        audience="mcp-server",
        issuer="mcp-auth"
    )
except jwt.InvalidTokenError as e:
    print(f"Token验证失败: {e}")

这里有几个关键点:

  • 算法白名单:只允许你预期的算法,别用algorithms=["HS256", "RS256"]这种写法,否则攻击者可以搞算法混淆攻击
  • 过期时间验证exp字段必须检查,我见过有人把过期时间设成2099年的
  • 签名密钥保护:私钥别硬编码在代码里,也别提交到Git仓库

避坑指南:我曾经在审计一个MCP插件时发现,开发者把JWT的secret key写在了config.py里,还上传到了公开的GitHub仓库。攻击者直接clone下来,伪造了任意用户的Token。嗯,从那以后我养成了习惯——先扫一遍代码里的硬编码密钥。

4.2 OAuth 2.0集成:授权码流程的陷阱

MCP协议支持OAuth 2.0作为认证方式,这在大规模部署时很常见。但OAuth 2.0的集成复杂度高,容易出问题。

标准的授权码流程是这样的:

  1. 客户端请求授权码
  2. 用户授权后,授权服务器返回授权码
  3. 客户端用授权码换取访问令牌
  4. 用访问令牌调用MCP接口

听起来简单对吧?但实际集成时,我见过太多翻车案例了。

常见漏洞:CSRF攻击、重定向URI劫持、授权码泄露、令牌存储不当。

举个例子,重定向URI劫持。有些MCP客户端在配置OAuth时,把重定向URI设成了http://localhost:8080/callback。攻击者可以在同一台机器上开个恶意服务,监听这个端口,截获授权码。我去年挖过一个类似的漏洞,攻击者通过这个方式拿到了用户的访问令牌,然后调用了MCP服务器上的敏感数据查询工具。

正确的做法是:

# OAuth 2.0 授权码流程 - 安全实现示例
import requests
from flask import Flask, request, session
import secrets

app = Flask(__name__)
app.secret_key = secrets.token_hex(32)

# 1. 生成并存储state参数,防止CSRF
@app.route('/auth/login')
def login():
    state = secrets.token_urlsafe(32)
    session['oauth_state'] = state
    
    auth_url = (
        f"https://auth.mcp-server.com/authorize?"
        f"response_type=code&"
        f"client_id=YOUR_CLIENT_ID&"
        f"redirect_uri=https://your-mcp-client.com/callback&"
        f"scope=tools:read resources:write&"
        f"state={state}"
    )
    return redirect(auth_url)

# 2. 验证state并交换令牌
@app.route('/auth/callback')
def callback():
    # 验证state,防止CSRF
    if request.args.get('state') != session.get('oauth_state'):
        return "CSRF攻击检测!", 403
    
    code = request.args.get('code')
    
    # 交换令牌 - 使用POST请求,不要在URL中传递code
    token_response = requests.post(
        "https://auth.mcp-server.com/token",
        data={
            'grant_type': 'authorization_code',
            'code': code,
            'redirect_uri': 'https://your-mcp-client.com/callback',
            'client_id': 'YOUR_CLIENT_ID',
            'client_secret': 'YOUR_CLIENT_SECRET'
        },
        headers={'Content-Type': 'application/x-www-form-urlencoded'}
    )
    
    tokens = token_response.json()
    # 安全存储令牌
    session['access_token'] = tokens['access_token']
    session['refresh_token'] = tokens.get('refresh_token')
    
    return "认证成功!"

这里有几个我特别想强调的点:

  • state参数必须用:别嫌麻烦,这是防CSRF的关键
  • redirect_uri要严格校验:最好用白名单,别用正则匹配
  • 授权码只能用一次:用完就失效,防止重放攻击
  • 令牌不要暴露在URL中:用POST请求,别用GET

4.3 会话管理漏洞分析

会话管理是MCP认证体系里最容易被忽视的一环。你想想看,Token认证和OAuth都做得再好,如果会话管理有漏洞,攻击者照样能绕过。

我总结了几类常见的会话管理漏洞:

漏洞类型 风险描述 修复建议
会话固定攻击 攻击者让用户使用已知的会话ID 登录后重新生成会话ID
会话劫持 攻击者窃取会话ID冒充用户 使用HTTPS、设置Secure/HttpOnly标志
会话超时不当 会话长期有效,增加泄露风险 设置合理的过期时间,实现空闲超时
并发会话控制缺失 同一用户多设备登录无限制 限制并发会话数,或实现踢下线机制

嗯,这里要特别说一下会话超时的问题。我在审计一个MCP服务器时发现,它的会话过期时间设成了24小时。你想想看,如果用户的Token泄露了,攻击者有整整一天的时间来搞破坏。更离谱的是,这个服务器还没有实现刷新令牌的轮换机制——也就是说,一个刷新令牌可以无限次使用。

避坑指南:我曾经在渗透测试中,通过抓包拿到了一个MCP客户端的会话Cookie。这个Cookie既没设HttpOnly,也没设Secure标志。我直接在浏览器里改了Cookie值,就成功冒充了管理员。嗯,从那以后我每次做安全审计,第一件事就是检查Cookie的安全属性。

安全的会话管理应该做到:

  • 会话ID要足够随机:别用时间戳、用户ID这种可预测的值
  • Cookie安全属性要齐全:HttpOnly、Secure、SameSite一个都不能少
  • 实现会话绑定:把会话ID和客户端IP、User-Agent绑定,增加劫持难度
  • 提供登出功能:登出时要清除服务端的会话记录,不只是删掉客户端的Cookie

4.4 知识体系总览

说了这么多,我画了张图帮你梳理一下MCP身份认证与授权的知识体系。这张图涵盖了Token认证、OAuth 2.0集成和会话管理三个核心模块,以及它们之间的关联关系。

MCP身份认证与授权知识体系 Token认证机制 • JWT签名验证 • 算法白名单 • 过期时间检查 • 密钥安全存储 • 算法混淆防御 • 硬编码密钥风险 OAuth 2.0集成 • 授权码流程 • CSRF防御(state) • 重定向URI校验 • 授权码一次性 • 令牌安全传输 • 重定向劫持风险 会话管理 • 会话ID随机性 • Cookie安全属性 • 会话绑定机制 • 超时策略 • 并发控制 • 会话固定/劫持 安全基础要求 HTTPS传输加密 | 最小权限原则 | 日志审计 | 速率限制 | 异常检测 常见攻击面 • Token伪造/篡改 • 授权码截获 • 会话劫持 • 重放攻击 • CSRF攻击 • 权限提升 • 密钥泄露 • 会话固定 • 暴力破解

这张图把整个认证授权体系分成了三层。最上面是三大核心模块,中间是安全基础要求,最下面是常见攻击面。你想想看,任何一个环节出了问题,攻击者都可能从最下面的攻击面找到突破口。

最后提醒一句:认证授权不是「配好了就完事」的东西。我建议你在MCP服务器上线前,至少做一次完整的认证授权安全审计。重点检查Token验证逻辑、OAuth回调处理、会话管理策略这三个方面。嗯,别问我为什么这么强调——都是踩过的坑换来的经验。


公众号:蓝海资料掘金营,微信deep3321