揭秘JOSE库中的DoS漏洞
JSON Web Tokens(JWT)和JSON对象签名与加密(JOSE)是广泛使用的标准,用于创建和验证基于JSON的加密/签名令牌。尽管这些标准相比传统方案有显著改进,但仍存在已知缺陷,例如JWT的"none"签名算法漏洞。
我们在BlackHat USA 2023会议上发现了一个新型JWT攻击——“十亿哈希攻击”。该攻击利用JWT密钥加密时缺乏迭代次数验证的特性,可导致拒绝服务。经同事Matt Schwager深入调查,发现该漏洞影响多个Go和Rust生态库:go-jose、jose2go、square/go-jose和josekit-rs。
这些库均支持通过PBES2方案进行密钥加密,该方案通过PBKDF2迭代从密码派生密钥。问题在于迭代次数通过令牌头部的p2c参数传递,攻击者可轻易篡改该值。例如以下恶意令牌头:
|
|
当应用程序尝试处理这种包含极大迭代次数的令牌时,需要先执行21亿次PBKDF2迭代才能验证令牌有效性,造成严重的计算资源消耗。
我们已向相关库维护者报告此问题,修复情况如下:
- go-jose/go-jose v3.0.1 限制p2c最大值
- jose2go v1.6.0 增加安全校验
- josekit-rs v0.8.5 实现防护措施
- square/go-jose因已弃用未修复,建议用户迁移
替代方案是严格校验算法参数。如果应用不预期接收PBES2算法令牌,应主动拒绝处理。jose2go已支持alg/enc参数严格校验,go-jose下个主版本将要求显式声明可接受算法列表。
无特权容器中的KASLR绕过漏洞
2020年,Trail of Bits工程师Dominik Czarnota发现Linux内核漏洞(未分配CVE),允许非特权Docker容器暴露内核指针地址,从而绕过内核地址空间布局随机化(KASLR)防护。
KASLR是操作系统关键防御机制,通过随机化内核内存地址阻止漏洞利用。内核地址应对用户空间隐藏,否则会削弱KASLR效果。理论上只有具备CAP_SYSLOG能力的进程才能查看内核地址(当/proc/sys/kernel/kptr_restrict=1时)。
但Dominik发现,在默认非特权Docker容器中,即使没有CAP_SYSLOG的root用户也能读取内核地址。根本原因是凭证检查存在缺陷:kptr_restrict=1时,内核未验证CAP_SYSLOG能力就直接暴露地址。该问题在commit b25a7c5af905中修复。
我们遵循协调披露流程,时间线如下:
- 2020-06-06:向Docker报告漏洞
- 2020-06-18:向Linux内核安全团队报告
- 2020-07-14:修复补丁并入Linux内核(4.19/5.4/5.7版本)
- Docker未修复其他sysfs信息泄露问题
漏洞披露时间线
2020年6月6日:向Docker报告漏洞
2020年6月11日:Docker回复建议向Linux内核报告
2020年6月18日:向security@kernel.org提交KASLR绕过漏洞
2020年6月30日:向Docker请求更新
2020年7月11日:再次联系Docker告知内核修复情况
2020年12月3日:最终尝试联系Docker未获回复
2024年还需要安全审计吗?
这两个漏洞类型迥异:JWT漏洞属于输入验证问题导致DoS,内核漏洞则是访问控制缺陷引发信息泄露。这种差异影响漏洞检测:
- DoS漏洞易通过服务中断被发现
- 访问控制漏洞通常难以察觉
自动化测试(如模糊测试)更易发现DoS漏洞,而检测访问控制漏洞需要实现验证逻辑。安全审计仍是发现漏洞的重要手段,我们建议将模糊测试与人工审计结合,通过强制安全约束捕获隐蔽的逻辑漏洞。