burpsuite网络安全学院: JWT attacks靶场通关
JWT authentication bypass via unverified signature(通过未验证签名绕过 JWT 身份验证)
本练习使用基于 JWT 的机制来处理会话。由于实现缺陷,服务器不会验证它收到的任何 JWT 的签名。
要解决该实验室问题,请修改您的会话令牌以访问 的管理面板 ,然后删除用户。/admincarlos
您可以使用以下凭据登录自己的帐户:wiener:peter
注意到 “sub” 声明(claim)中包含你的用户名。将此请求发送到 “Burp 中继器(Burp Repeater)”。
向此端点(endpoint)发送请求,即可完成该实验。
JWT authentication bypass via flawed signature verification
(通过存在缺陷的签名验证绕过JWT身份验证 )
JWT authentication bypass via weak signing key
(通过弱签名密钥绕过 JWT 身份验证)
JWT(JSON Web Token)由三部分组成:header、payload、signature。签名用于确保 token 未被篡改。
常见绕过原因:
第 1 部分 - 暴力破解密钥
注意:若多次运行此命令,需添加 “--show” 参数,才能再次在控制台输出结果。
第 2 部分 - 生成伪造的签名密钥
第 3 部分 - 修改并签名 JWT
JWT authentication bypass via jwk header injection
(通过 JWK 标头注入实现的 JWT 身份验证绕过)
1) 简要概念与攻击思路(高层、可理解)
2) 常见触发条件(为什么会发生)
3) 风险
注意事项
除了使用 JWT Editor 扩展插件内置的攻击功能外,你也可以通过手动方式在 JWT 标头中添加jwk参数来嵌入 JWK。在此情况下,你还需要更新令牌的kid(密钥 ID)标头,使其与嵌入密钥的kid值保持一致。
JWT authentication bypass via jku header injection
(通过 JKU 标头注入实现的 JWT 身份验证绕过)
1) 概念 — 什么是 jku header 注入?
2) 为什么会发生(常见触发条件)
3) 风险
第一部分 - 上传恶意 JWK 集合
{ |
{ |
第二部分 - 修改并签名 JWT
JWT authentication bypass via kid header path traversal
(通过 kid 标头路径遍历实现的 JWT 身份验证绕过)
1) 概念与攻击高层
2) 常见触发条件)
3) 风险
注意事项
本解决方案中,我们会将kid参数指向标准文件/dev/null。在实际场景中,你可将kid参数指向任何内容可预测的文件。
生成合适的签名密钥
修改并签名 JWT
JWT authentication bypass via algorithm confusion
(通过算法混淆实现的 JWT 身份验证绕过)
1) 什么是算法混淆攻击(高层)
JWT header 包含 alg 字段,表示签名算法(例如 HS256、RS256 等)。算法混淆利用服务端在验证时对 alg 的信任或处理不当:攻击者更改 alg 或构造与 key 类型不一致的组合(例如把 alg
从 RS256 改为 HS256),利用服务器把公钥当作 HMAC secret 或接受 alg: none,从而伪造 token、绕过认证或提升权限。
常见变种包括但不限于:
2) 为什么会发生(根本原因)
3) 风险
第一部分 - 获取服务器公钥
{ |
第二部分 - 生成恶意签名密钥
-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwvrunJIBFsK6LFROQAqN zhNC30Y/V6OXRheCXEqGpKnFEcS7rHcNMun6cCvo5AhTL0pKYDjqUeUq/UvSDW5i 5Yf2xcAz+6EUNf5L6qxiI+IHYDFnhj3pv3bSedOVfXLq66WYaWsB/3os0D2uvFD/ m+oqj3ZxQRftMlkkgu2Yo3a6V8Q/kKvVhVxoy3bfjmPf0DymBY9xqi8KO/PQgnw7 AK5OAJhAoeaY2qdu6JoiFzLi8l9rvr9Vo5H0YBENrHQlNrLR69JZ5c5wUyqVsP9y RyqrXqihLFLqzh8GlvCsmyO+C0czxOFkLy9lHDOdPcw5FlMwxIEpm/ttI1AmP+uF 0QIDAQAB -----END PUBLIC KEY----- |
第三部分 - 修改并签名令牌
原理分析与总结
一、攻击核心思路(一句话)
攻击者把 服务端公钥 当作 HMAC(对称)密钥 来使用:先从服务器可访问的 JWKS 获取公钥,把它转换成对称密钥,然后把 JWT 的 alg 改为 HS256 并用该“对称密钥”签名——如果服务端信任 header 中的 alg 并用公钥当作 HMAC secret 验证,就会通过签名,从而伪造任意 claims(例如 sub=administrator)。
二、攻击流程(抽象化的关键步骤)
三、为什么会发生(根本原因)
四、可观测的检测信号(用于监控与事后分析)
JWT authentication bypass via algorithm confusion with no exposed key
通过无暴露密钥的算法混淆实现 JWT 身份验证绕过
补充说明:
一、场景与前提
二、红队侦察
目标是收集可用于识别潜在风险点的信息,而不是直接利用。常用无侵入/低侵入方法包括:
必要提醒:所有以上动作都必须在授权范围内并控制影响。任何主动篡改或攻击步骤都应记录并在测试计划/授权中明确。
三、容易被利用的高层触发面
这些是你在评估时重点排查的“逻辑错误类别”——每一项都是高风险点,但我只做概念性描述,不给具体 exploit 步骤。
第一部分 - 获取服务器生成的两个 JWT
第二部分 - 暴力破解服务器公钥
第三部分 - 生成恶意签名密钥
第四部分 - 修改并签名令牌
- 返回 Burp Repeater 中的请求,将路径修改为/admin。
- 切换到由扩展插件生成的 “JSON Web Token” 标签页。
- 在 JWT 的标头(header)中,确保alg(算法)参数已设置为HS256。
- 在 JWT 的负载(payload)中,将sub声明的值修改为administrator(表示将用户身份改为管理员)。
- 在该标签页底部,点击 “Sign”(签名),然后选择你在之前步骤中生成的对称密钥。
- 确保已选中 “Don't modify header”(不修改标头)选项,然后点击 “OK”。此时,修改后的令牌已使用服务器的公钥作为密钥完成签名。
- 发送该请求,观察结果可知,你已成功访问管理员面板。
- 在响应内容中,找到用于删除 carlos 用户的 URL(路径为/admin/delete?username=carlos)。向该端点发送请求,即可完成实验任务。
- 在终端窗口中,复制上一部分中已确认正确的 Base64 编码 X.509 格式公钥。注意:需选择公钥本身,而非上一步中使用的篡改后 JWT。
- 在 Burp 中,进入 “JWT Editor Keys”(JWT 编辑器密钥)标签页,点击 “New Symmetric Key”(新建对称密钥)。
- 在弹出的对话框中,点击 “Generate”(生成)以创建 JWK 格式的新密钥。
- 将生成的k属性值替换为你刚才复制的 Base64 编码公钥。注意:此处需填入公钥本身,而非上一步中使用的篡改后 JWT。
- 保存该密钥。
- 在终端中运行以下命令,将两个 JWT 作为参数传入:
docker run --rm -it portswigger/sig2n <第一个令牌> <第二个令牌>
注意:首次运行该命令时,可能需要几分钟时间从 Docker Hub 拉取镜像。 - 观察命令输出,其中会包含一个或多个计算得出的n值(RSA 公钥的模数)。这些值在数学上均有可能是目标公钥的模数,但只有一个与服务器实际使用的值匹配。无论哪种情况,输出内容还会包含以下信息:
- 分别以 X.509 格式和 PKCS1 格式编码的 Base64 公钥;
- 使用每个计算出的公钥签名的篡改后 JWT。
- 复制第一个 X.509 格式条目对应的篡改后 JWT(若仅输出一个条目,则直接复制该条目下的篡改后 JWT)。
- 返回 Burp Repeater 中的请求,将路径改回/my-account。
- 将会话 Cookie 替换为刚才复制的新 JWT,然后发送请求。
- 验证结果:
- 若收到 200 响应且成功访问账号页面,说明该 X.509 格式公钥是正确的;
- 若收到 302 响应(重定向至/login且清除了你的会话 Cookie),说明该 X.509 格式公钥是错误的。这种情况下,需使用脚本输出的每个 X.509 格式公钥对应的篡改后 JWT,重复此步骤进行验证。
- 在 Burp 中,从 BApp 商店加载 JWT Editor(JWT 编辑器)扩展插件。
- 在实验环境中,登录你自己的账号,并将登录后的 GET 请求(路径为/my-account)发送到 Burp Repeater(重放器)。
- 在 Burp Repeater 中,将请求路径修改为/admin并发送请求。观察结果可知,仅当以管理员(administrator)用户身份登录时,才能访问管理员面板。
- 复制你的 JWT 会话 Cookie,并保存到某处备用。
- 退出登录,然后重新登录。
- 复制新的 JWT 会话 Cookie,同样保存起来。此时你已拥有两个由服务器生成的有效 JWT。
- Fail-open / 回退到默认对称 Secret
- 验证代码在找不到 key(kid 未命中、JWKS 拉取失败)时错误地使用某个全局对称 secret 或默认值来验证签名,造成用 HMAC 可伪造 token 的条件。
- 密钥混用 / 环境变量共享
- 运维把 RSA 私钥/公钥和 HMAC secret 放在同一配置项或相邻变量(例如同一 env 名),导致验证逻辑在不同 alg 场景下错误地使用同一字符串作为 secret。
- 没有校验 key 类型(kty)与 alg 的匹配
- 动态 key 查找后没验证返回 key 的类型,直接把“字符串/PEM 文本”当成 HMAC secret 使用。
- 错误/宽松的库配置
- 未在 verify 调用中显式设置 algorithms,或使用旧版库默认宽松行为(接受 none 或自动回退)。
- 错误的错误处理或吞噬异常
- key 查找异常被捕获但未拒绝请求(记录后允许继续),造成间接回退或逻辑漏洞。
- 跨服务可信度差异
- 微服务间共享同一 token 验证逻辑但配置不统一(一个服务 fail-closed,另一个 fail-open),攻击面扩大。
- 功能面枚举
- 识别哪些端点需要 JWT(登录、API、管理页面等)。
- 找出 token 的签发与验证链路(登录返回 token 的端点、token 刷新、微服务间调用点)。
- Header / Token 观测
- 抓取有效 token(属于测试账号/授权账号)。分析 header(alg、kid、typ、jku/jwk 等字段),注意有没有非常规字段。
- 观察 token 的签名类型(RS/HS/none)以及是否带 kid、jku、jwk。
- 错误路径与异常行为探测
- 在授权范围内触发典型异常(例如请求用缺失或篡改 kid 的 token),观察返回码与日志行为(403/401 还是 500 / 信息泄露)。
- 观察当 key lookup 失败或 JWT 验证库报错时的响应差异(是否有回退或不同的错误处理)。
- 依赖与库识别
- 通过响应头、页面脚本、公开代码仓库或错误信息判断后端技术栈与可能使用的 JWT 库(有助于推测默认行为/已知危险配置)。
- 密钥/配置暴露搜索(被动)
- 搜索公开仓库、配置泄露、备份文件或错误页面中可能泄露的配置(仅被动搜索,有授权时可扩展)。
- 目标:服务使用 JWT 对请求做认证/鉴权,正常场景为非对称签名(如 RS256),但没有公开 JWKS / 公钥(或公钥不可访问于普通用户)。
- 你做的是:授权渗透测试/红队评估(必须有书面允许)。
- 关注点:在“没有公开密钥”的前提下,是否依然存在算法混淆导致的绕过(例如失败回退、密钥混用、错误的 key 类型校验、错误的错误处理等)。
- 算法混淆(algorithm confusion):指攻击者利用 JWT 验证逻辑漏洞,篡改令牌标头中的alg(算法)参数(如将非对称算法 RS256 改为对称算法 HS256),诱导服务器使用错误算法验证令牌的攻击手段。
- 无暴露密钥(no exposed key):区别于 “有暴露密钥” 的算法混淆场景(如服务器通过/jwks.json公开公钥),此场景下服务器未主动暴露任何用于签名验证的密钥(公钥或对称密钥),攻击者需通过其他方式(如利用服务器逻辑缺陷、默认密钥等)获取或构造可用于伪造签名的密钥。
- JWT(JSON Web Token):一种轻量级令牌格式,常用于网络应用的身份验证与信息传递,由标头(Header)、负载(Payload)和签名(Signature)三部分组成。
- 身份验证绕过(authentication bypass):攻击者未提供合法身份凭证(如正确密码、有效令牌),却通过技术手段绕开系统身份验证流程,非法获取访问权限的行为。
- 突然出现以 HS256 等对称 alg 签发但 iss/kid 指向本应使用 RS 的 token。
- 日志中出现很多“签名通过,但 header.alg 与 key 类型不匹配”的警告(如果已有此类检查)。
- 请求中频繁包含 jwk、jku 或非常规 kid 值(尤其是来自外部/匿名 IP)。
- JWKS 端点在短时间内被大量抓取或访问异常(可能被用来收集公钥)。
- 单次会话中 token alg 发生异常变化(例如登录后 token alg 与访问时 token alg 不一致)。
- 服务端 key 查找路径/行为异常(从非受信任源取 key 的请求记录)。
- 信任客户端提供的 alg 字段:把 header 的 alg 当作决定验证方式的唯一权威(而非由服务器端配置/issuer 映射来决定)。
- 公/私钥与对称密钥混淆:服务端在选择验证 key 时没有校验 key 的类型,可能将 RSA 公钥文本误当作 HMAC secret。
- 动态或不受控的 key 解析流程:比如代码允许从 token header(jwk/jku/kid)动态获取或构建 key,而缺乏受信任来源校验。
- 不安全的库默认或错误使用:部分库/样例易于被误用(例如不传 algorithms 白名单),或默认接受 none。
- 错误的错误处理或回退逻辑:在找 key 失败时回退到默认弱 secret、或错误地转换 key 表示也会放大风险。
- 获取受信任公钥:访问公开的 JWKS(例如 /jwks.json),复制某个公钥(JWK)。
- 把公钥转换为对称 secret:将公钥以某种格式(例如 PEM 的 Base64)作为对称密钥的原始材料(即 HMAC secret)。
- 篡改 token header:将 alg 从 RS256(或其它非对称算法)改为 HS256。
- 伪造 payload:把 sub 或角色改为期望的高权限值(例如 administrator)。
- 使用“公钥作为 secret”签名:用上一步生成的对称 secret 对 header+payload 做 HMAC 签名,生成新的 token。
- 服务端验证:若服务端在验证时 信任 token header 指定的算法,并且使用同一来源的 key(此处是公钥/秘钥混淆),就会把公钥当作 HMAC secret 去验证,签名通过,从而实现认证绕过。
- 发送该请求,观察结果可知,你已成功访问管理员面板。
- 在响应内容中,找到用于删除 carlos 用户的 URL(路径为/admin/delete?username=carlos)。向该端点发送请求,即可完成实验任务。
- 在该标签页底部,点击 “Sign”(签名),然后选择你在之前步骤中生成的对称密钥。
- 确保已选中 “Don't modify header”(不修改标头)选项,然后点击 “OK”。此时,修改后的令牌已使用服务器的公钥作为密钥完成签名。
- 在负载(payload)中,将sub声明的值修改为administrator(表示将用户身份改为管理员)。
- 返回 Burp Repeater 中的 GET /admin 请求,切换到由扩展插件生成的 “JSON Web Token” 标签页。
- 在 JWT 的标头(header)中,将alg(算法)参数的值修改为HS256。
- 保存该密钥。
- 返回 Burp 主标签栏中的 “JWT Editor Keys” 标签页。
- 点击 “New Symmetric Key”(新建对称密钥)。在对话框中,点击 “Generate”(生成)以创建 JWK 格式的新密钥。注意:无需选择密钥长度,后续系统会自动更新此参数。
- 将生成的k属性值替换为你刚才创建的 Base64 编码 PEM 字符串。
- 切换到 “Decoder”(解码器)标签页,对该 PEM 密钥进行 Base64 编码,然后复制编码后的字符串。
- 右键点击你刚创建的密钥条目,然后选择 “Copy Public Key as PEM”(将公钥复制为 PEM 格式)。
- 在 Burp 中,点击主标签栏中的 “JWT Editor Keys”(JWT 编辑器密钥)标签页。
- 点击 “New RSA Key”(新建 RSA 密钥)。
- 在弹出的对话框中,确保已选中 “JWK” 选项,然后粘贴你刚才复制的 JWK。点击 “OK” 保存该密钥。
- 从keys数组内部复制 JWK 对象。注意确保不要误复制数组周围的任何字符。
- 在浏览器中,访问标准端点/jwks.json,观察到服务器会暴露一个 JWK 集合(JWK Set),其中包含一个公钥。
- 在 Burp 中,从 BApp 商店加载 JWT Editor(JWT 编辑器)扩展插件。
- 在实验环境中,登录你自己的账号,并将登录后的 GET 请求(路径为/my-account)发送到 Burp Repeater(重放器)。
- 在 Burp Repeater 中,将请求路径修改为/admin并发送请求。观察结果可知,仅当以管理员(administrator)用户身份登录时,才能访问管理员面板。
- 伪造任意 claims(如 sub=admin),导致权限提升、数据泄露、后端资源滥用。
- 在微服务/跨域验证场景下放大攻击面(多个服务共享同一验证逻辑)。
- 隐匿性强——看起来像合法 token,日志也许只显示签名通过。
- 信任 token header 的 alg(把 header 当作可信配置)。
- 将公钥/私钥混淆使用:例如在 RS256 场景下不小心用公钥作为 HMAC secret,或在代码中使用了错误的 key 类型。
- 未强制算法白名单:未在 verify() 调用中显式规定允许的算法。
- 使用不安全或过时的 JWT 库/默认行为:有些库早期版本允许 none 或在配置不当时做危险的回退。
- 错误的 key 管理/查找逻辑:动态选择 key 时未校验 key 类型/来源。
- 把 alg 从非对称(RS256)改为对称(HS256),并把服务端的公钥当作 HMAC secret 来验证(若服务器实现错误,会通过)。
- 使用 alg: none(若库/实现允许)导致跳过签名验证。
- 服务端未校验 alg 白名单或信任 header 中的 alg,并据此选择验证方式。
- 在响应内容中,找到用于删除 carlos 用户的 URL(路径为/admin/delete?username=carlos)。向该端点发送请求,即可完成实验任务。
- 发送该请求,观察结果可知,你已成功访问管理员面板。
- 在该标签页底部,点击 “Sign”(签名),然后选择你在之前步骤中生成的对称密钥。
- 确保已选中 “Don't modify header”(不修改标头)选项,然后点击 “OK”。此时,修改后的令牌已使用空字节作为密钥完成签名。
- 在 JWT 的负载(payload)中,将sub声明的值修改为administrator(表示将用户身份改为管理员)。
- 返回 Burp Repeater 中的 GET /admin 请求,切换到由扩展插件生成的 “JSON Web Token” 消息编辑标签页。
- 在 JWT 的标头(header)中,将kid参数的值修改为指向/dev/null文件的路径遍历序列:
../../../../../../../dev/null - 点击 “OK” 保存该密钥。
- 将生成的k属性值替换为 Base64 编码的空字节(即AA==)。需注意,这只是一种临时解决方案 —— 因为 JWT Editor 扩展插件不允许使用空字符串为令牌签名。
- 点击 Burp 主标签栏中的 “JWT Editor Keys”(JWT 编辑器密钥)标签页。
- 点击 “New Symmetric Key”(新建对称密钥)。
- 在弹出的对话框中,点击 “Generate”(生成)以创建 JWK 格式的新密钥。注意:无需选择密钥长度,后续系统会自动更新此参数。
- 在 Burp 中,从 BApp 商店加载 JWT Editor(JWT 编辑器)扩展插件。
- 在实验环境中,登录你自己的账号,并将登录后的 GET 请求(路径为/my-account)发送到 Burp Repeater(重放器)
- 在 Burp Repeater 中,将请求路径修改为/admin并发送请求。观察结果可知,仅当以管理员(administrator)用户身份登录时,才能访问管理员面板。
- 通过指定恶意 kid 可让验证逻辑加载错误的 key(甚至私钥或攻击者上传的 key),从而伪造 token 或直接使签名验证通过。
- 泄露敏感文件(私钥、配置、凭证)。
- 横向影响:多个服务共享同一 key 查找逻辑时,问题将被放大。
- 直接使用 kid 拼接文件路径而未做白名单或正规化。
- 将 kid 用于数据库查询或文件路径时缺乏输入验证与最小权限。
- key 存放在本地文件系统且文件名由 kid 可控地映射(例如 keys/{kid}.pem)而没有安全检查。
- 缺乏集中、受控的 key 管理(本地散乱文件 + 可供 web 进程访问的路径)。
- 代码在查找 key 失败时出现错误处理缺陷(返回默认 key 或忽略验证),导致“失败为成功”。
- kid(Key ID)是 JWT header 中的元数据,用于在服务器端从一组密钥中定位用于验证的密钥。常用做法:服务端根据 kid 去 JWKS、数据库或本地文件系统查找公钥。
- 若实现把 kid 直接当作文件路径片段使用(例如 fs.readFileSync('/keys/' + kid))而且没有正确校验或规范化 kid,攻击者可提供包含 ../、绝对路径或 URL 等特殊值的 kid 来进行路径遍历或指向任意文件,从而让验证代码加载攻击者控制或敏感文件(例如私钥、配置文件),导致签名绕过或泄露。
- 本质上属于“不信任来自客户端的标识符” + “不安全的文件/路径处理” 的组合缺陷。
- 确保已选中 “Don't modify header”(不修改标头)选项,然后点击 “OK”。此时,修改后的令牌已使用正确的签名完成签名操作。
- 发送该请求。观察结果可知,你已成功访问管理员面板。
- 在响应内容中,找到用于删除 carlos 用户的 URL(路径为/admin/delete?username=carlos)。向该端点发送请求,即可完成实验任务。
- 在负载(payload)中,将sub声明的值修改为administrator(表示将用户身份改为管理员)。
- 在该标签页底部,点击 “Sign”(签名),然后选择你在之前步骤中生成的 RSA 密钥。
- 在 JWT 的标头中添加一个新的jku参数,将其值设置为你在漏洞利用服务器上存储 JWK 集合的 URL。
- 返回 Burp Repeater 中的 GET /admin 请求,切换到由扩展插件生成的 “JSON Web Token” 消息编辑标签页。
- 在 JWT 的标头(header)中,将当前kid参数的值替换为你上传到漏洞利用服务器的 JWK 所对应的kid值。
- 将复制的 JWK 粘贴到漏洞利用服务器的keys数组中,然后点击 “Store”(保存)漏洞利用代码。最终结果应类似如下格式:
- 返回 “JWT Editor Keys” 标签页,右键点击你刚生成的密钥条目,然后选择 “Copy Public Key as JWK”(将公钥复制为 JWK 格式)
- 将 “Body”(正文)部分的内容替换为以下空 JWK 集合:
- 在浏览器中,访问漏洞利用服务器(exploit server)。
- 点击 Burp 主标签栏中的 “JWT Editor Keys”(JWT 编辑器密钥)标签页。
- 点击 “New RSA Key”(新建 RSA 密钥)。
- 在弹出的对话框中,点击 “Generate”(生成)以自动创建新的密钥对,然后点击 “OK” 保存该密钥。注意:无需选择密钥长度,后续系统会自动更新此参数。
- 在 Burp Repeater 中,将请求路径修改为/admin并发送请求。观察结果可知,仅当以管理员(administrator)用户身份登录时,才能访问管理员面板。
- 在 Burp 中,从 BApp 商店加载 JWT Editor(JWT 编辑器)扩展插件。
- 在实验环境中,登录你自己的账号,并将登录后的 GET 请求(路径为/my-account)发送到 Burp Repeater(重放器)。
- 攻击者可伪造任意 claims(例如把自己设为 admin)并访问受保护资源。
- 如果服务对多个 issuer 或第三方服务开放,攻击面更大。
- 可能被滥用跨服务访问(若多个服务共享验证逻辑)。
- 验证实现直接读取 jku 并从该 URL 拉取 JWKS,然后用返回的 key 验证签名,而未检查该 URL 是否为受信任来源或与 iss 绑定。
- 未对 jku 的域名/路径做白名单或与 issuer 做映射校验。
- 未限制 alg 或未校验 key 类型与 alg 的一致性。
- 使用的 JWT 库(或中间件配置)提供方便选项来“自动从 jku 拉取 key”,而开发者未意识到风险或未做额外限制。
- JWT header 中可包含 jku(JSON Web Key Set URL),用于指向一个 JWKS(公钥集合)位置(RFC 7515 支持)。
- 攻击思路(高层):若服务端在验证 token 时盲目信任 header 中的 jku URL,攻击者可以把 jku 指向其控制的 URL,提供自己的公钥集合,从而让伪造的 token 被服务端接受,造成认证绕过或权限提升。
- 关键问题点:把 token header 当作可信配置(信任由客户端提供的 key source)。
- 在响应内容中,找到用于删除 carlos 用户的 URL(路径为/admin/delete?username=carlos)。向该端点发送请求,即可完成实验任务
- 发送该请求。观察结果可知,你已成功访问管理员面板。
- 查看 JWT 的标头(header),可发现已添加一个jwk参数,其中包含你的公钥。
- 在 “JSON Web Token” 标签页的底部,点击 “Attack”(攻击),然后选择 “Embedded JWK”(嵌入 JWK)。出现提示时,选择你刚生成的 RSA 密钥,点击 “OK”。
- 返回 Burp Repeater 中的 GET /admin 请求,切换到由扩展插件生成的 “JSON Web Token” 标签页。
- 在负载(payload)中,将sub声明的值修改为administrator(表示将用户身份改为管理员)。
- 在弹出的对话框中,点击 “Generate”(生成)以自动创建新的密钥对,然后点击 “OK” 保存该密钥。注意:无需选择密钥长度,后续系统会自动更新此参数。
- 点击 Burp 主标签栏中的 “JWT Editor Keys”(JWT 编辑器密钥)标签页。
- 点击 “New RSA Key”(新建 RSA 密钥)
- 在 Burp Repeater 中,将请求路径修改为/admin并发送请求。观察结果可知,仅当以管理员(administrator)用户身份登录时,才能访问管理员面板。
- 在 Burp 中,从 BApp 商店加载 JWT Editor(JWT 编辑器)扩展插件。
- 在实验环境中,登录你自己的账号,并将登录后的 GET 请求(路径为/my-account)发送到 Burp Repeater(重放器)。
- 攻击者可以伪造任意声明(例如 sub=admin)并获得高权限。
- 横向攻击:伪造的 token 可用于访问其他微服务或 API(若这些服务共享验证逻辑)。
- 隐蔽性高:看起来像“合法 token”,而且签名通过。
- 验证逻辑使用 header 提供的 jwk 字段直接构建公钥并验证签名,而不验证该 key 的来源或是否在受信任的 key set(例如授权的 JWKS URI)中存在。
- 支持在 header 中直接传 jwk(RFC 7515 允许),但如果实现没有额外校验就会被滥用。
- 服务端接受任意 alg 或在算法与 key 类型之间没有做交叉验证(例如 header 指明 alg: RS256,但 key 是对称 HMAC 类型)。
- 未严格校验 kid 与被信任 JWKS 的对应关系,或直接用 header 的 key 覆盖本地 key lookup。
- JWT 的 header 可包含 alg、kid,以及可选的 jwk 字段(RFC 7515 支持在 header 中直接嵌入 JSON Web Key)。
- 攻击的核心思路是:服务端在验证 JWT 时信任 token header 中提供的 jwk(或直接接受 header 中的公钥),并用该公钥验证签名。这允许攻击者:
- 使用自己控制的密钥对伪造的 token 签名,然后把对应的公钥放入 token header 的 jwk 字段,服务端如果直接读取并信任它,就会通过验证,从而实现认证绕过或权限提升。
- 这种问题一般是服务端实现/配置错误导致:把 header 内容当作可信密钥来源,而没有把 header 中的 key 限定为来自可信的 JWKS(key set)或已注册的密钥。
- 在响应内容中,找到用于删除 “carlos” 的 URL(地址),即 “/admin/delete?username=carlos”。向此端点(endpoint)发送请求,即可完成该实验。
- 确保勾选 “不修改头部”(Don't modify header)选项,然后点击 “确定”(OK)。此时,修改后的令牌已使用正确的签名完成签名。
- 发送请求,观察到你已成功访问管理员面板。
- 在该标签页底部,点击 “签名”(Sign),然后选择上一部分中你生成的密钥。
- 返回 Burp 中继器中 “GET /admin” 请求的页面,切换到由扩展生成的 “JSON Web Token” 消息编辑标签页。
- 在载荷(payload)中,将 “sub” 声明(claim)的值修改为 “administrator”。
- 点击 “确定”(OK)保存该密钥。
- 将生成的密钥中 “k” 属性的值替换为前面 Base64 编码后的密钥。
- 在弹出的对话框中,点击 “生成”(Generate),以 JWK(JSON Web Key)格式生成一个新密钥。注意:无需选择密钥长度,后续系统会自动更新。
- 在 Burp 中,进入 “JWT 编辑器密钥”(JWT Editor Keys)标签页,点击 “新建对称密钥”(New Symmetric Key)。
- 使用 Burp 解码器(Burp Decoder),对前一部分中暴力破解得到的密钥进行 Base64 编码。
- 复制该 JWT(JSON Web Token)并对其密钥进行暴力破解。你可以使用 hashcat 工具,通过以下命令实现:
hashcat -a 0 -m 16500 eyJraWQiOiI4NmZlY2FhYi03MzdiLTQ4MmUtODJlNi00N2VjMjgzYmNlYzciLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTc1Njk0ODEyMCwic3ViIjoid2llbmVyIn0.fdg0nvws_cRCFBMbnu_sRBt0KXFqz75glMNvCagBWbI /usr/share/wordlists/rockyou.txt
若使用 hashcat,命令执行后会输出 JWT 令牌,其后紧跟对应的密钥。若操作无误,结果会显示该弱密钥为 “secret1”。 - 在 Burp 中继器中,将请求路径修改为 “/admin” 并发送请求。观察到只有以 “administrator”(管理员)用户身份登录时,才能访问管理员面板。
- 在 Burp 中,从 BApp 商店加载 JWT 编辑器扩展(JWT Editor extension)。
- 在实验环境中,登录你自己的账号,并将登录后的 “GET /my-account” 请求发送到 Burp 中继器(Burp Repeater)。
- 弱签名密钥:HMAC(HS256/HS512 等)使用对称密钥;如果密钥太短或易猜(比如“secret”、“1234”),攻击者能暴力/猜解后伪造任意 payload 并签名。
- 算法混淆/替换:服务器没有强制检查 alg,攻击者将 alg 改为 none 或把公钥算法(RS256)改为对称算法(HS256)并用公钥当作 HMAC secret,从而欺骗服务器。
- 不完整验证:只验证签名但忽略 iss/aud/exp/nbf 等断言;或验证时未限制允许的 alg 列表。
- 密钥管理差:密钥泄露、未轮换、以源码/环境变量明文存储且权限过宽
- 发送请求,观察到你已成功访问管理员面板。
- 在响应内容中,找到用于删除 “carlos”(目标用户)的 URL(地址),该 URL 为 “/admin/delete?username=carlos”。向此端点(endpoint)发送请求,即可完成该实验。
- 在消息编辑器(message editor)中,删除 JWT 中的签名(signature)部分,但需注意保留载荷后面的末尾点号(.)。
- 选中 JWT 的头部(header)部分,接着通过检查器将 “alg” 参数(算法参数)的值修改为 “none”,点击 “应用更改(Apply changes)”。
- 再次选中 JWT 的载荷部分。在检查器面板中,将 “sub” 声明的值修改为 “administrator”,然后点击 “应用更改(Apply changes)”。
- 在 Burp 中继器中,将请求路径修改为 “/admin” 并发送请求。观察到只有以 “administrator”(管理员)用户身份登录时,才能访问管理员面板。
- 双击该令牌的载荷(payload)部分,在 “检查器(Inspector)” 面板中查看其解码后的 JSON 格式。注意到 “sub” 声明(claim)中包含你的用户名。将此请求发送到 “Burp 中继器(Burp Repeater)”
- 在 Burp(抓包工具)中,进入 “代理(Proxy)”>“HTTP 历史记录(HTTP history)” 标签页,找到登录后的 “GET /my-account” 请求。观察到你的会话 Cookie 是一个 JWT(JSON Web Token)。
- 在实验环境中,登录你自己的账号。
- 在响应内容中,找到用于删除 “carlos”(目标用户)的 URL(地址),该 URL 为 “/admin/delete?username=carlos”。
- 再次发送请求。观察到你已成功访问管理员面板
- 再次选中 JWT 的载荷部分。在检查器面板中,将 “sub” 声明的值从 “wiener”(普通用户名,示例)修改为 “administrator”,然后点击 “应用更改(Apply changes)”。
- 在 Burp 中继器中,将请求路径修改为 “/admin” 并发送请求。观察到只有以 “administrator”(管理员)用户身份登录时,才能访问管理员面板
- 双击该令牌的载荷(payload)部分,在 “检查器(Inspector)” 面板中查看其解码后的 JSON 格式。
- 在 Burp(抓包工具)中,进入 “代理(Proxy)”>“HTTP 历史记录(HTTP history)” 标签页,找到登录后的请求。观察到你的会话 Cookie 是一个 JWT(JSON Web Token),对应的请求为 “GET /my-account”。
- 在实验环境中,登录你自己的账号。