OAuth 2.0 已成为现代 Web 应用身份授权的基石,从“使用 Google 登录”到企业级单点登录,几乎无处不在。然而,其灵活的授权流程和多样的实现方式,也为攻击者留下了可乘之机。本文将深入剖析 OAuth 2.0 中三类高危漏洞:重定向劫持、CSRF 攻击与令牌泄露,并结合实际案例探讨防御策略。
一、OAuth 2.0 核心流程回顾
在讨论漏洞之前,有必要简要回顾 OAuth 2.0 的授权码模式(Authorization Code Grant),这是最常用也最易出问题的流程:
- 用户访问客户端应用,点击“登录”。
- 客户端将用户重定向至授权服务器,携带
client_id、redirect_uri、scope、state等参数。 - 用户在授权服务器上认证并同意授权。
- 授权服务器将用户重定向回
redirect_uri,并附带一个授权码code。 - 客户端后端使用
code向授权服务器换取访问令牌access_token。 - 客户端使用令牌访问受保护资源。
漏洞往往出现在第 2、4、5 步的参数校验与状态管理环节。
二、重定向劫持:redirect_uri 校验不严
漏洞原理
redirect_uri 是 OAuth 流程中最为关键的参数之一。授权服务器在用户授权后,会将授权码发送到该地址。如果授权服务器对 redirect_uri 的校验过于宽松,攻击者就可以篡改该参数,将授权码劫持到自己的服务器。
常见的校验缺陷包括:
- 前缀匹配:只检查
redirect_uri是否以合法域名开头,例如https://legit.com.evil.com可通过。 - 通配符滥用:允许
https://*.legit.com,攻击者注册https://evil.legit.com即可。 - 路径穿越:
https://legit.com/callback/../../evil可能绕过路径限制。 - 未校验参数:完全信任客户端提交的
redirect_uri。
攻击场景
攻击者构造如下链接,诱导用户点击:
https://auth-server.com/authorize?
client_id=legit-client&
redirect_uri=https://evil.com/capture&
response_type=code&
scope=read
用户认证后,授权码被发送至 evil.com。攻击者再用该授权码换取访问令牌,从而完全接管用户账户。
防御措施
- 授权服务器必须对
redirect_uri进行精确匹配,仅允许预先注册的完整 URI。 - 禁止使用通配符或前缀匹配。
- 客户端应使用
state参数绑定会话,并在回调时验证。
三、CSRF 攻击:state 参数缺失或可预测
漏洞原理
OAuth 2.0 的 state 参数旨在防止跨站请求伪造(CSRF)。它由客户端生成并随授权请求发送,授权服务器在回调时原样返回。客户端需验证返回的 state 是否与用户会话中保存的值一致。
如果 state 缺失、固定不变或可预测,攻击者可以伪造授权回调,将受害者账户绑定到攻击者的 OAuth 身份上,或反之。
攻击场景
假设某网站允许用户通过 OAuth 绑定第三方账号。攻击者先用自己的第三方账号发起授权,获取授权码,然后构造回调链接:
https://victim-site.com/oauth/callback?code=ATTACKER_CODE
诱导受害者点击。如果受害者已登录且 state 未校验,系统会将攻击者的第三方账号绑定到受害者账户。此后,攻击者即可通过自己的第三方账号登录受害者的账户。
防御措施
- 强制使用
state参数,并确保其随机、不可预测(如使用加密安全的随机数生成器)。 - 将
state与用户会话绑定,回调时严格比对。 - 对于绑定操作,要求用户二次确认。
四、令牌泄露:隐式模式与日志泄露
漏洞原理
OAuth 2.0 的隐式授权模式(Implicit Grant)直接将 access_token 作为 URL 片段(fragment)返回给客户端。虽然片段不会发送到服务器,但可能被浏览器历史、Referer 头、前端日志或恶意脚本泄露。
此外,授权码模式中,如果客户端未正确保护 code 和 access_token,也可能导致泄露:
- Referer 泄露:回调页面包含第三方资源时,
code可能通过 Referer 头泄露。 - 日志记录:服务器或代理日志记录完整 URL,包含
code。 - 浏览器历史:
code留在浏览器历史中,可被本地攻击者获取。 - 开放重定向:授权服务器自身存在开放重定向,攻击者可利用其窃取令牌。
攻击场景
某应用使用隐式模式,令牌出现在 URL 片段中:
https://client.com/#access_token=SECRET&token_type=bearer
页面中嵌入了一个第三方分析脚本,该脚本读取 location.hash 并将数据发送至攻击者服务器。令牌瞬间泄露。
防御措施
- 弃用隐式模式,优先使用授权码模式 + PKCE(Proof Key for Code Exchange)。
- 授权码应一次性使用,短有效期,且绑定客户端。
- 避免在 URL 中传递敏感信息;使用 POST 或后端通道。
- 设置
Referrer-Policy: no-referrer,防止 Referer 泄露。 - 对令牌进行加密存储,限制访问范围。
五、综合防御建议
- 严格校验 redirect_uri:精确匹配,禁止通配符。
- 强制使用 state 参数:随机生成,会话绑定,一次有效。
- 采用 PKCE:即使对于公共客户端,也能有效防止授权码拦截。
- 使用授权码模式:避免隐式模式,令牌仅通过后端通道传输。
- 短令牌有效期与刷新令牌轮换:降低泄露后的影响。
- 安全日志与监控:避免记录敏感参数,监控异常授权行为。
- 定期安全审计:对 OAuth 实现进行渗透测试与代码审查。
结语
OAuth 2.0 本身是一个授权框架,而非认证协议。其安全性高度依赖于实现细节。重定向劫持、CSRF 与令牌泄露这三类漏洞,往往源于对规范理解的偏差或开发中的疏忽。只有严格遵循最佳实践,并结合 PKCE、state 校验、精确重定向等机制,才能构建真正安全的授权体系。对于安全从业者而言,理解这些漏洞的成因与利用方式,是进行有效防御的第一步。
未经允许不得转载:任鹏个人博客 » OAuth 2.0 授权漏洞剖析:重定向劫持、CSRF 与令牌泄露

