有缺陷的 JWT 签名验证

当 JWT 的签名验证存在缺陷,会发生什么?

Tip

推荐先阅读文章:什么是 JWT?

不验证签名#

如果你了解 JWS,会认为:

怎么会有人愚蠢到用了 JWS 但是不验证签名。

但这通常不是开发者有意为之。

部分开发者在使用某些 JWT 库的时候,可能:

  • 对某些函数的实现并不是非常清楚
  • 想当然地以为某个函数包含了验签算法(“既然你提供了 JWS 的实现,想必你已经在该函数中实现了验签了吧”)
  • ……

导致“验证签名”并没有被实现。

none 算法#

JWS 中有一个特殊的验签算法,即:

Text
{"alg":"none"}

这将不采用任何算法去进行签名验证。

在 none 算法中,JWS 紧凑序列化的组成如下:

Text
BASE64URL(UTF8(JWS Protected Header)).BASE64URL(JWS Payload).
Attention

注意保留末尾的 .。

Burp Suite 的 JWT Editor 插件,提供了该攻击的模板:

Tip

如果你还不了解该插件,请阅读文章:在 Burp Suite 中处理 JWT

点击后,会让你选择 none 的一些正常或者变体写法以应对不同的情况:

选择完毕后,点击“OK”,你会发现此时的 JWT 已经变成下述模样:

Text
BASE64URL(UTF8(JWS Protected Header)).BASE64URL(JWS Payload).

并且在 Header 中的 alg 参数的值已经变为了你指定的 none:

暴力破解密钥#

某些签名算法(例如 HS256(HMAC + SHA-256))使用任意的独立字符串作为密钥(和密码一样):

Text
u9+udaYDqC1+2Hw2faJszg==
umeshSecret
notesApp#12345
serucity_is_secure_beacuse_it_is
@token2F5e84cb2610411b048c16probono4e60553855ebd5827918
!@2222222fasdhiohDCWQA
replace_with_lengthy_secure_hex
Info

上述信息截取自著名字典 SecLists。

在某些场景中,比如:

  • 使用了一些常见密钥
  • 默认密钥
  • 短密钥(可穷举)
  • ……

攻击者可以通过 hashcat 等工具本地破解密钥。原理很简单,签名保护的内容是 Header 与 Payload,这对用户都是可见信息,只需要根据算法,配合字典中的密钥,进行重新签名操作,签名得到的结果与正确的签名进行比对,相同的签名则意味着密钥对了。

Hashcat 中的模式(mode,-m 参数)选择 16500,破解示例:

Bash
hashcat -a 0 -m 16500 eyJraWQiOiI5ZGE0OWVmZS02OTRmLTQ1ZTQtYmM0My01NThiZDIwNjZiNDEiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTc5MjIyNjY0Miwic3ViIjoid2llbmVyIn0.HM-v7ER_aojM-EcCAfPwIqzmw3eq4Ubciood5MuhISc /usr/share/seclists/Passwords/scraped-JWT-secrets.txt
Note

-a 用于选择攻击模式,其中 0 为 Straight 模式(默认选择 0),hashcat 会逐行读取 wordlist 中的每个词作为候选密钥。

Burp Suite Scanner 同样也会尝试本地破解密钥(通过其内置的字典),如果发现破解成功了则会在 All issues 中报告给用户:

但是,该方法基本只适用于目标使用了对称签名算法的情况,因为非对称签名算法所使用的公钥通常很长且熵极高,基本不可能被破解成功。

如果你获得了签名所使用的密钥(以 secret1 为例),接下来你可以切换到 JWT Editor 面板,并选择“New Symmetric Key”,在弹出的窗口中将密钥填入到 Specify secret 中的文本框中:

点击“Generate”之后就生成了对应的密钥,并且会在 Key 中给出 JWK 格式的密钥:

接下来回到 Repeater 中,对你修改后的 JWT 进行重签名操作:

在弹出的窗口中,选择你刚刚创建的新密钥(通过 ID),并且勾选针对 Header 的一些操作:

点击 OK 之后,插件就会生成新的 Signature(如果你还勾选了一些修改 Header 的选项,还会修改 Header)。

键盘快捷键

全站

CtrlK
搜索
/
搜索
?
显示快捷键
Esc
关闭弹窗、退出模式

阅读文章

T
目录
F
专注模式
A
批注模式

批注模式

P
笔
H
荧光笔
L
激光笔
E
橡皮擦
1–6
切换颜色
Shift
按住拖动画直线
CtrlZ
撤销
CtrlShiftZ
重做