OAuth 2.0 已成为现代 Web 与移动端第三方登录的事实标准,但其协议设计的灵活性和实现层面的疏漏催生了大量高危漏洞。本文聚焦可操作的利用手法,覆盖重定向 URI 绕过、CSRF、PKCE 降级、scope 越权、令牌泄露、Device Flow 滥用及 OpenID Connect(OIDC)特有攻击面,并以六大认证协议横向对比辅助架构选型。
一、认证协议全景对比
选错协议往往是安全风险的起点——用 API Key 做用户登录、用 SAML(Security Assertion Markup Language,安全断言标记语言)对接移动端,这类架构层面的错配比单个漏洞更难修复。
| 对比维度 | OAuth 2.0 + OIDC | SAML 2.0 | CAS 3.x | API Key | Basic Auth | OAuth 1.0a |
|---|---|---|---|---|---|---|
| 核心定位 | 第三方授权 + 通用 SSO、C 端快捷登录 | 政企跨组织企业级单点登录 | 轻量化内部 Web 单点登录 | 服务间 API 鉴权(无用户参与) | 内网简易接口鉴权、测试环境 | 老旧第三方授权协议(已淘汰) |
| 数据载体 | JSON、JWT 令牌 | XML 安全断言 | TGT 全局票据、ST 单次服务票据 | 请求头 / URL 参数 | Base64 编码账号密码 | HMAC 签名请求参数 |
| 支持客户端 | 网页、APP、小程序、SPA(PKCE 适配) | 仅 PC 浏览器,移动端适配极差 | 仅 Web 网页,不支持原生 APP | 仅后端服务端程序 | 全类型客户端 | 仅服务端后端 |
| 第三方授权 | 是(微信 / 谷歌登录授权) | 支持跨企业用户身份互通 | 仅内部可信系统,不对外 | 无用户概念,只代表应用 | 固定账号,无用户授权流程 | 支持第三方授权 |
| 凭证时效 | access_token 短期,refresh_token 自动续期 | 一次性断言,不可复用 | TGT 长期登录态,ST 单次有效 | 永久有效,需人工重置 | 永久账号凭证 | 长期有效令牌 |
| 权限控制 | scope 细粒度权限,可单独撤销 | 基于角色 / 属性配置企业级权限 | 仅校验登录身份,无标准权限体系 | 全局全接口权限,无法细分 | 固定全部接口权限 | scope 授权,灵活性差 |
| 安全依赖 | 强依赖 HTTPS,无内置签名 | HTTPS + XML 证书双重校验 | 必须 HTTPS 防止票据劫持 | 建议 HTTPS,密钥泄露风险极高 | 强制 HTTPS,否则密码明文传输 | 内置参数签名,不强制 HTTPS |
| 集成难度 | 低,标准化 HTTP 接口,SDK 丰富 | 高,XML 解析、证书维护复杂 | 中等,开源 SDK 完善,仅适配网页 | 极低,请求头填入即可 | 极低,标准 HTTP 原生协议 | 极高,每次请求需签名计算 |
| 场景 | 微信 / GitHub 登录、飞书 / 钉钉 SaaS、Google / Azure | 国企、银行、政务平台、高校教务、SAP / Oracle ERP | 高校校园统一登录、中小企业内网 OA | 阿里云 / AWS 开放 API、高德地图、OpenAI 后端调用 | 运维监控、内部测试接口、简易管理后台 | 早年 Twitter、豆瓣存量系统,新项目完全弃用 |
| 核心优缺点 | 优势:全端适配、生态成熟;劣势:token 泄露造成权限盗用 | 优势:企业合规、跨组织隔离;劣势:移动端难集成 | 优势:开源免费、部署简单;劣势:仅网页,无对外授权 | 优势:接入最简单;劣势:密钥泄露则全接口失守 | 优势:零接入成本;劣势:每次传输凭证,安全薄弱 | 优势:无 HTTPS 也有基础安全;劣势:流程繁琐,已被淘汰 |
选型速查:C 端 → OAuth 2.0 + OIDC;企业内 Web(AD 域)→ SAML 2.0;轻量内部 Web → CAS 3.x;服务间调用 → API Key + IP 白名单;测试环境 → Basic Auth;OAuth 1.0a → 弃用。
二、OAuth 2.0 与 OIDC 核心机制
2.1 角色与授权码流程
OAuth 2.0 四类角色:客户端(请求数据)、资源所有者(用户)、授权服务器(认证并颁牌)、资源服务器(托管数据)。OIDC 中对应依赖方、最终用户、OpenID 提供者。
授权码流程(Authorization Code Grant)是目前最主流的授权类型,核心在于授权码兑换令牌在服务器端完成,对浏览器不可见。客户端将用户重定向至 /authorize,携带 client_id、redirect_uri、response_type=code、scope、state。用户登录同意后,授权服务器 302 重定向将授权码发往 redirect_uri。客户端服务器向 /token 发送 POST,以授权码和 client_secret 交换 access_token。
2.2 隐式流程
跳过授权码交换,令牌直接放在 URL fragment 中:/callback#access_token=abc123&token_type=Bearer&expires_in=3600。全程经浏览器,已被最佳实践废弃,但存量系统大量存在。
2.3 OIDC 扩展
标准化 scope(openid 必选)、ID Token(JWT 格式身份令牌,由授权服务器签名)、动态客户端注册(向 /register 端点自助注册)。
三、核心攻击面与利用手法
3.1 重定向 URI 攻击
redirect_uri 是授权码和令牌的流向终点,绕过白名单校验即等于控制用户身份。
路径遍历:
1 | redirect_uri=https://trusted.example.com/callback/../evil.example.com/callback |
子域名混淆(利用后缀匹配缺陷):
1 | redirect_uri=https://evil.trusted.example.com/callback |
URL 解析差异(@ 前被视为用户信息):
1 | redirect_uri=https://trusted.example.com@evil.example.com/callback |
fragment 干扰:
1 | redirect_uri=https://trusted.example.com/callback%23@evil.example.com |
空字节截断:
1 | redirect_uri=https://trusted.example.com%00.evil.example.com/callback |
参数污染(提交两个 redirect_uri,测后端取哪个校验、哪个跳转):
1 | redirect_uri=https://trusted.example.com/callback&redirect_uri=https://evil.example.com |
localhost 放宽(利用允许 http://localhost/callback 的实现做 SSRF 接收令牌)。
开放重定向代理。当 redirect_uri 被精确校验为白名单域名时,利用该域内的开放重定向做跳板:
1 | redirect_uri=https://trusted.example.com/callback/../../redirect?next=https://evil.example.com |
postMessage 窃取。回调页面通过 postMessage 向任意来源发送令牌:
1 | parent.postMessage({token: access_token}, "*"); |
攻击者用 <iframe> 嵌入回调 URL,通过 addEventListener('message', ...) 监听窃取。
Mix-Up。多授权服务器场景下,攻击者诱导客户端将授权码发往自己控制的授权服务器,再由后者代表受害者向真实授权服务器发起请求。利用条件:客户端未将每个授权服务器的 redirect_uri、issuer、令牌端点做严格一一绑定。
3.2 流程控制缺陷
State 参数缺失 → CSRF。缺失 state 时,攻击者发起自己的 OAuth 流程获取授权码,构造指向该回调 URL 的恶意页面发给受害者。受害者已在目标应用登录,浏览器触发回调后服务端将攻击者的社交账户绑定到受害者账户,攻击者通过自己的社交账户登录即接管。
会话固定。攻击者在自己浏览器中获取半完成的授权会话,将 state 和授权 URL 注入受害者环境。受害者完成授权后,授权码关联到攻击者预置的会话。移动端因浏览器与应用间会话边界模糊,此攻击危害更大。
PKCE 降级。PKCE(Proof Key for Code Exchange,RFC 7636)可选时,攻击者移除 code_challenge 参数,授权服务器回退到无 PKCE 流程。截获授权码后在令牌交换时不需 code_verifier 即可获取令牌。更深层绕法:在受害者发起授权请求前将 code_challenge 替换为自己的 code_verifier 对应值。
Scope 越权。授权码流中在令牌交换时追加 scope;隐式流中直接修改授权请求中的 scope。
Consent Phishing。注册名为”安全合规工具””IT 助手”等欺骗性 OAuth 应用,钓鱼诱导用户在合法授权页面点击同意。MFA 对此无效——用户在完成 MFA 后主动授权。2024 年 Chrome 扩展供应链攻击即用此手法影响了 260 万以上用户。
未验证邮箱注册。授权服务器不验证邮箱时,用目标用户邮箱在授权服务器注册,再通过 OAuth 登录目标应用,利用 email claim 信任链冒充受害者。
3.3 令牌安全
隐式流令牌泄露。令牌在 URL fragment 中,若误放在查询参数中则 Referer 头直接泄露;浏览器历史、服务器日志、用户复制分享也都会泄露。
Audience 混淆。ID Token 的 aud 未精确匹配 client_id 或仅做子串匹配时,其他应用签发的 ID Token 可跨应用登录。
Audience Injection(2025)。使用 private_key_jwt 客户端认证时,若 aud 同时接受颁发者标识符和令牌端点 URL 两种格式,攻击者可将一个端点获取的合法 JWT 注入另一个端点的请求中。签名有效导致授权服务器无法区分。IETF 已修订 RFC 7523,要求 aud 统一使用颁发者标识符。
ID Token 签名绕过:设 alg: none 篡改 payload;从 /.well-known/jwks.json 获取公钥后将算法改为 HS256 签名;不验证 exp 则令牌永不过期;不验证 nonce 则跨会话重放。
3.4 OIDC 特有攻击面
动态注册 SSRF。OIDC 提供方不要求认证时,直接向 /register 发 POST 注册客户端,设置 logo_uri 为内网地址,授权页面加载图片时发起 SSRF。
Claims 注入。OIDC 的 claims 请求参数允许指定希望返回的声明值,若服务器未校验即写入令牌,可注入 "email": "admin@example.com" 实现身份伪造(CVE-2025-64099)。
Request Object 绕过。支持 request_uri 时,JWT 内嵌参数的校验可能比 URL 查询参数宽松,借此绕过 redirect_uri 白名单。
跨应用 COAT / CORF。集成平台共享同一授权服务器时,若只追踪”哪个应用”而非”哪个 AS + 哪个应用”,攻击者授权一个恶意应用后可跨应用接管其他账户。CVE-2023-36019(CVSS 9.6)一次点击接管 Outlook + Azure Key Vault。
3.5 Device Flow 攻击
Device Authorization Grant(RFC 8628)为输入受限设备设计:客户端请求设备码 → 用户用另一设备访问验证 URL 输入设备码 → 授权服务器轮询令牌端点 → 用户确认后颁发令牌。
2024—2025 年 ShinyHunters 攻击链:
- LinkedIn 收集目标企业员工信息
- 冒充 IT 致电员工,引导其访问
login.microsoftonline.com输入攻击者提供的设备码 - 员工完成 MFA 认证并看到真实的授权同意页面
- 授权服务器将 token 发给攻击者设备
- 通过合法 API 窃取 Salesforce 等 CRM 数据,流量表现为正常 API 调用
已确认受害者包括多家跨国企业。利用点:MFA 保护认证但不阻止用户在认证后主动授权恶意应用。
四、防御措施
授权服务提供方:
redirect_uri逐字节精确匹配,每个应用实例独立 URI- 强制
state与会话 cookie 通过哈希绑定 - 强制 PKCE,拒绝无
code_challenge的请求 - 令牌交换时验证
redirect_uri、client_id、scope 与初始请求一致 - 动态注册要求认证;
claims参数实施白名单 - 客户端 JWT 认证
aud统一使用颁发者标识符 - 非必要场景禁用 Device Flow
客户端应用方:
/authorization和/token同时发送redirect_uristate严格校验;移动端/桌面端额外校验回调请求来源- 全类型客户端启用 PKCE +
nonce - 验证 ID Token 签名、
iss、aud、exp、nonce - 不同授权服务器使用独立回调 URI
- 不将邮箱声明作为唯一身份锚点,首次 SSO 要求补充验证
- 废弃隐式流,迁移至授权码 + PKCE
- 回调页面设
Referrer-Policy: no-referrer