CVE-2018-0114

客户端可通过 JWT Header 中的 `jwk` 或者 `x5c` 参数自行指定验签密钥,导致客户端可构造出合法 JWT。

漏洞卡片#

node-jose 是 Node.js 中的一个有关 JOSE(JSON Object Signing and Encryption)的代码库。

Note

JOSE 是一套密码学标准规范框架,它提供了一种轻量化的方式让使用 JSON 数据结构的数据能在网络上安全地传输。

影响版本:< 0.11.0

漏洞发现者:Fraser Winterborn

Tip

漏洞发现者没有针对该漏洞写专门的博客。

漏洞简述:客户端可通过 JWT Header 中的 jwk 或者 x5c 参数自行指定验签密钥,导致客户端可构造出合法 JWT。

Info

该攻击手段可参考这篇文章。

CWE-347:Improper Verification of Cryptographic Signature(不当的密码学签名验证)

Base Score:7.5 HIGH

Vector:  CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N

漏洞讲解#

Info

建议先了解 JWT。

verify.js(文件路径:lib/jws/verify.js):

如果 JWT 中的 Header 部分存在:

  • jwk 参数,或者
  • x5c 参数

则其值会充当后续验签算法所需要的密钥。

Tip

对这两个参数的介绍可参考文章。

这意味着攻击者可以(以 jwk 为例):

  1. 根据算法,本地生成密钥对(通过 Burp Suite 的 JWT Editor 插件或者 Python 脚本)
  2. 在 JWT Header 中提供 jwk 参数并赋值 JWK 格式的公钥(刚刚生成的)
  3. 修改 JWT Header 中的 kid 参数为 jwk 中对应的 kid
  4. 修改 JWT(以达成某种目的,比如可将 Payload 中的 role 声明的值改为 admin)
  5. 用配对私钥(刚刚生成的)进行签名,生成 Signature
  6. 发送合法 JWT
Tip

如果对此过程有疑惑,下面几篇文章也许能帮助到你:

针对 jwk 的利用,建议使用 Burp Suite,在这篇文章中详细展示了步骤,这里不再赘述。

当然也可以通过 Python 脚本来实现利用,Poc(假设目标采用 RS256 验签算法):

Tip

上述 JWT 中的 Header 以及 Payload 中的内容均为示例,具体根据实际情况。

针对 x5c 的利用,推荐使用 Python 脚本,Poc(假设目标采用 RS256 验签算法):

Poc 中,对证书链我添加了额外的一张由 Root CA 签发的证书(用于验证 Leaf),这仅仅只是为了 Python 实现上的方便,按 node-jose 源码,它并不会查看除 Leaf 外的第二张证书。

Diff#

关键 diff:

Diff
- if (sig.header.jwk) {
+ if (opts.allowEmbeddedKey && sig.header.jwk) {
    algKey = JWK.asKey(sig.header.jwk);
- } else if (sig.header.x5c) {
+ } else if (opts.allowEmbeddedKey && sig.header.x5c) {

在判断中引入了变量 opts.allowEmbeddedKey,该变量的默认值为 False,这意味着默认不会参考客户端在 JWT Header 中提供的 jwk 以及 x5c 参数。

除非开发者自行修改 opts.allowEmbeddedKey,比如设置了“在某场景中会参考 JWT Header 中提供的 jwk 以及 x5c 参数”,代码是否安全都取决于开发者自己的实现逻辑了。

推测安全研究员的发现经过#

JWT 本身就应该给予高度关注。

CheckLists#

代码库。

练习#

PentesterLab 上对应的练习题。

参考文章#

键盘快捷键

全站

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

阅读文章

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

批注模式

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