JWT 认证机制下的越权漏洞分析与渗透测试实践
在企业 SSO 架构下因 JWT 实现缺陷导致的越权漏洞。通过梳理 SSO 登录至子系统访问的流程,揭示了 UID 与 Token 绑定不严格的安全隐患。文章详细阐述了 JWT 的结构、常见攻击方式如 Alg None 和签名绕过,并结合实际案例展示了如何通过修改 UID 实现任意用户数据访问。最后提供了 Python 模拟代码及具体的修复方案,包括强制签名校验、Claim 绑定验证及最小权限原则,旨在帮助开发人员识别并防御此类身份认证漏洞。

在企业 SSO 架构下因 JWT 实现缺陷导致的越权漏洞。通过梳理 SSO 登录至子系统访问的流程,揭示了 UID 与 Token 绑定不严格的安全隐患。文章详细阐述了 JWT 的结构、常见攻击方式如 Alg None 和签名绕过,并结合实际案例展示了如何通过修改 UID 实现任意用户数据访问。最后提供了 Python 模拟代码及具体的修复方案,包括强制签名校验、Claim 绑定验证及最小权限原则,旨在帮助开发人员识别并防御此类身份认证漏洞。

在现代企业级应用架构中,单点登录(SSO)已成为主流的身份认证方案。用户通过统一的身份源进行登录,随后访问多个子系统时通常采用无状态令牌(如 JWT, JSON Web Token)进行会话管理。这种架构虽然提升了用户体验和系统解耦能力,但也引入了新的安全风险。
本文基于一次真实的渗透测试案例,深入分析在 SSO 集成场景下,由于 JWT 校验逻辑缺陷导致的越权访问漏洞。该案例涉及 Oracle WebCenter 作为统一认证入口,下游业务系统依赖 JWT 进行资源访问控制。通过对请求流程的抓包分析和签名验证逻辑的逆向推导,我们发现了 UID 与 Token 绑定不严格的问题,并实现了任意用户的权限提升。
JSON Web Token (JWT) 是一种开放标准 (RFC 7519),用于在各方之间安全地传输信息。JWT 由三部分组成,使用点号分隔:
一个典型的 JWT 结构如下所示:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
在安全审计中,针对 JWT 的攻击主要集中在以下三个方面:
sub 或 role)并重放。alg 字段修改为 none。如果服务端未强制校验签名算法,可能会接受空签名的 Token。本次测试的目标系统采用 SSO + JWT 的混合架构。用户首先通过 Oracle WebCenter 进行身份认证,获取 Session 后,再调用内部 OAM 接口换取子系统的 JWT Token。整个流程分为以下几个关键步骤:
在分析第三个包的响应数据时,我们发现返回的 JSON 中包含 UID 字段,且该字段并未被包含在 JWT 的 Payload 中进行签名保护,或者服务端在验证时仅校验了 Token 格式而未校验 Token 内信息与当前请求参数的匹配度。
具体表现为:攻击者可以截获一个合法用户的 JWT Token,然后修改请求参数中的 UID 为其他用户的 ID。由于服务端未将 UID 与 Token 中的 sub 或自定义 Claim 进行强一致性校验,导致服务器接受了非法的 UID 映射,从而返回了非授权用户的数据。
通过遍历不同的 UID 值,攻击者可以批量获取系统中所有用户的敏感信息,包括但不限于账户基本信息、未读消息、菜单权限及操作按钮等。这种水平越权漏洞使得低权限用户可以完全接管高权限账户的功能视图。
为了更清晰地展示漏洞原理,以下提供一段基于 Python 的模拟代码,演示如何构造恶意 JWT 并利用 alg: none 绕过签名验证。
import jwt
import json
# 原始 Payload
payload = {
"sub": "admin",
"uid": "10086",
"exp": 9999999999
}
# 尝试使用 alg=None 生成 Token
try:
# 注意:这通常需要服务端存在 Alg None 漏洞才能生效
token = jwt.encode(payload, key="", algorithm="none")
print(f"Generated Token: {token}")
except Exception as e:
print(f"Error: {e}")
# 如果服务端允许 None 算法,攻击者可直接修改 Payload 中的 sub 字段
malicious_payload = {
"sub": "attacker",
"uid": "10086"
}
# 假设已知密钥或可绕过签名
在实际场景中,如果无法绕过签名,攻击者会尝试修改 Payload 中的 sub 字段以切换身份,前提是服务端未校验签名。若服务端校验签名但密钥较弱,则可使用工具如 jwt_tool 进行爆破。
该漏洞属于高危级别,具体风险包括:
针对此类 JWT 越权漏洞,建议从以下几个方面进行加固:
alg: none 算法。sub)与请求参数中的业务标识(如 UID)进行比对。如果不一致,应直接拒绝请求。JWT 作为一种轻量级的认证方案,其安全性高度依赖于服务端的实现质量。在复杂的微服务架构中,开发者容易忽视 Token 与业务数据的关联校验,从而导致越权漏洞。通过本次案例分析,强调了在开发过程中进行安全编码审查的重要性,特别是在处理身份认证和授权逻辑时,必须遵循'零信任'原则,对所有输入数据进行严格验证。
对于安全研究人员而言,在进行渗透测试时,应重点关注 Token 的生命周期管理、签名算法的配置以及业务逻辑层面的参数校验,切勿放过任何一个 HTTP 请求包。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online