JWT 弱密钥:Hashcat 与 JWT Editor 实战笔记

记录 JWT 弱密钥靶场中的签名原理、Hashcat 字典测试与结果查看,以及 JWT Editor 导入密钥和重新签名的流程。

  • #JWT
  • #弱密钥
  • #Hashcat
  • #Burp Suite
  • #身份认证

本文记录授权靶场中的学习过程。示例中的弱密钥与身份字段用于说明原理,不代表所有应用都使用相同配置。

一、核心知识逻辑:为什么要这么做?

JWT 的常见签名形式由三部分组成:Header.Payload.Signature。

以 HS256 为例,签名计算可以写成:

signingInput = Base64URL(Header 的 UTF-8 字节) + "." + Base64URL(Payload 的 UTF-8 字节)
Signature = Base64URL(HMAC-SHA256(key=Secret, message=signingInput))

这里的 Base64URL 编码省略末尾的 = 填充。校验已有 Token 时,应使用它原有的前两段作为签名输入,不能把 JSON 重新排版后再比较签名。

  • 致命缺陷: 如果服务端使用了弱密钥,例如 123456、dragon,就可能通过字典猜出这个 Secret。弱密钥不等于一定能被当前字典命中。
  • 权限提升: 找到 Secret 后,可以修改 Payload,并用相同密钥重新签名。例如将 "role":"user" 改为 "role":"admin"。能否获得管理员权限,取决于后端是否信任该字段,以及是否还有其他身份、权限和有效期校验。

二、工具实战手法:两种模式

1. Burp JWT Editor:手工验证与重新签名

  1. 在 JWT Editor 或 JWT Editor Keys 中新建对称密钥。如果版本提供 Specify secret 明文输入选项,直接填入已找到的 Secret,由插件完成编码。
  2. 如果直接编辑 JWK,注意 k 字段填写的是密钥字节的 Base64URL 编码,不是明文 Secret,不要把两种输入方式混淆。
  3. 先使用候选密钥验证原始 Token 的签名,再到 Repeater 的 JSON Web Token 标签页修改 Payload。
  4. 点击 Sign,选择对应密钥重新签名,保持靶场原本使用的 HS256 算法。
  5. 发送请求,结合响应正文、跳转位置和实际权限判断结果。

不能把“302 = 密钥错误,200 = 密钥正确”当作通用规则。 302 可能是正常跳转,200 也可能返回登录页或错误提示。密钥是否匹配原签名、请求是否通过身份认证、是否获得目标权限,是不同的判断。

当前官方 JWT Editor 支持 Attack → Weak HMAC secret。不同版本的菜单可能有差异,没有该功能时可以使用下方的 Hashcat 方法。参见 JWT Editor 官方说明。

2. Hashcat:离线字典测试

先把抓到的完整原始 JWT 保存为 jwt.txt,一行一个 Token。不要包含 Bearer 、Cookie 名称、引号或换行拆分;也不要先改 Payload,否则就不是在验证服务器原本生成的签名了。

下面的命令假设已经安装 Hashcat,并准备好 jwt.txt 和解压后的 rockyou.txt。文件不在当前目录时,需要填写实际路径;rockyou.txt 不会由命令自动下载。

命令一:使用字典测试候选密钥

hashcat -m 16500 -a 0 jwt.txt rockyou.txt
部分 含义
hashcat 启动 Hashcat。
-m 16500 指定 JWT 模式;本文用于 HS256 签名的共享密钥测试,不是破解 RS256 私钥。
-a 0 使用直接字典模式,依次将字典中的条目作为候选密钥。
jwt.txt 待验证的完整 JWT 文件,是测试目标,不是字典。
rockyou.txt 候选密钥字典,通常每行一个候选值。可以换成自己准备的靶场字典。

执行时,Hashcat 用每个候选 Secret 对原 JWT 的前两段计算签名,再与第三段比较。这是本机离线计算,不是逐条向网站发送登录请求。参见 PortSwigger 的 JWT 弱密钥说明。

常见结果可以这样理解:

  • Recovered: 1/1 (100.00%):加载的一个目标已经找到匹配密钥;不代表网站管理员权限已经验证成功。
  • Status: Cracked:目标已破解完成,可以查看恢复出的密钥。
  • Status: Exhausted 且 Recovered: 0/1:当前候选已尝试完但没有匹配,不代表密钥一定安全。

命令二:查看已经找到的密钥

hashcat -m 16500 --show jwt.txt
  • -m 16500:仍按相同 JWT 模式识别输入。
  • --show:把 jwt.txt 中的目标与 Hashcat 的结果缓存(potfile)比较,显示已经恢复出的结果,不会重新跑字典。
  • jwt.txt:指定要查询哪些 Token 的结果,所以这里不再需要 -a 0 和 rockyou.txt。

默认输出通常由“原 JWT”和“恢复出的密钥”组成,中间用冒号分隔。下面只是格式示意,dragon 不代表这次实际恢复出的值:

原JWT字符串:dragon

如果没有输出,先检查是否已经破解成功、是否使用同一份目标文件,以及两次运行是否使用同一个 potfile。此前禁用了缓存、清除了缓存或切换了运行环境,也可能查不到结果。缓存包含恢复出的密钥,不应提交到博客仓库。

参数含义可对照 Hashcat 官方文档。在 Windows PowerShell 中,如果程序位于当前目录且未加入 PATH,可将命令开头的 hashcat 换成 ./hashcat.exe。

三、完整的攻击链(Attack Chain)

  1. 截取凭证: 浏览器登录靶场,Burp 拦截包含 JWT 的请求。
  2. 破解密钥: 将原始 JWT 交给 Hashcat,或使用 JWT Editor 的弱 HMAC 密钥测试功能尝试字典。
  3. 篡改身份: 拿到明文密钥后,在 JWT Editor 中导入该密钥,将 Payload 里的 "role":"user" 改为 "role":"admin";字段以实际靶场的授权逻辑为准。
  4. 伪造签名: 点击 Sign,用找到的密钥重新计算签名,再发送请求验证权限变化。

四、复盘 Tips

  • 弱密钥利用是用找到的密钥重新生成有效签名,与“服务器不验证签名”不同。 所以这次修改 Payload 后需要重新签名,不能照搬上一篇保留原签名的测试方式。
  • 共享密钥字典测试针对 HS256 等 HMAC 算法,不能直接套到 RS256 私钥上。 本文的具体命令以 HS256 为例,其他算法需要确认工具和模式是否支持。