JSON Web令牌DoS漏洞与Linux内核KASLR绕过技术解析

本文深入分析了JOSE库中因PBES2迭代次数未验证导致的拒绝服务漏洞,以及Linux内核中权限容器可绕过KASLR防护的信息泄露漏洞,涵盖技术原理、影响范围和修复方案。

从内核到令牌:Trail of Bits漏洞挖掘纪实

揭秘JOSE库中的DoS漏洞

JSON Web令牌(JWT)和JSON对象签名与加密(JOSE)是描述基于JSON的加密/签名令牌创建与使用的广泛标准。虽然这些标准相比早期身份声明方案有重大改进,但仍存在已知缺陷,例如JWT"none"签名算法漏洞。

我们的发现涉及BlackHat USA 2023上Tom Tervoort提出的新型JWT攻击之一:“十亿次哈希攻击”。该攻击利用JWT密钥加密缺乏验证的缺陷导致拒绝服务,引起我们同事Matt Schwager的注意。进一步调查发现,该漏洞影响Go和Rust生态的多个库:go-jose、jose2go、square/go-jose和josekit-rs。

这些库均支持使用PBES2进行密钥加密,该功能允许基于密码加密JWE中的内容加密密钥(CEK)。密钥首先通过PBES2方案从密码派生,执行多次PBKDF2迭代,然后用于加密和解密令牌内容。

问题在于迭代次数通过令牌中的p2c头部参数传递,攻击者可轻易篡改。例如以下令牌头部:

图1:显示使用大量迭代次数的PBES2密钥加密的JWE令牌头部

通过在p2c字段使用极大迭代次数,攻击者可导致任何尝试处理该令牌的应用发生DoS。接收方需要先执行2,147,483,647次PBKDF2迭代派生CEK,才能验证令牌有效性,消耗大量计算时间。

我们向相关库维护者报告了该问题,并已在以下版本修复:go-jose/go-jose 3.0.1(提交65351c27657d)、dvsekhvalnov/jose2go 1.6.0(提交a4584e9dd712和8e9e0d1c6b39)、hidekatsu-izuno/josekit-rs 0.8.5(提交1f3278a33f0e等)。square/go-jose因已弃用未修复,建议用户迁移至go-jose/go-jose。

替代方案是不完全依赖令牌的alg参数。如果应用不预期接收使用PBES2或冷门算法的令牌,则无需处理此类令牌。jose2go现已支持对alg和enc参数实施严格验证,go-jose的下个主要版本将在处理令牌时要求传递可接受算法列表。

无权限容器中的KASLR绕过

接下来是2020年已修复但未分配CVE的内核漏洞。我们将详细分析这个此前未知但已修复的KASLR绕过漏洞。

2020年,Trail of Bits工程师Dominik Czarnota发现Linux内核漏洞可能暴露无特权Docker容器内的内部指针地址,允许攻击者绕过内核模块的KASLR防护。

KASLR是操作系统中的重要防御机制,通过随机化内核内存地址位置阻止漏洞利用。内核地址必须对用户空间隐藏,否则地址泄露将直接绕过KASLR防护。

虽然存在向用户空间程序显示内核地址的情况,但在多数系统中,这应仅限具有CAP_SYSLOG Linux能力的用户。CAP_SYSLOG能力手册页明确说明:“当/proc/sys/kernel/kptr_restrict值为1时,查看通过/proc和其他接口暴露的内核地址。”

但Dominik发现,在Docker容器中,无CAP_SYSLOG能力的root用户进程仍可观察内核地址。默认情况下,Docker容器无特权,意味着root用户权限受限(例如无法执行需要CAP_SYSLOG的操作)。该问题也可通过capsh工具在无Docker环境下复现。

根本原因是凭据检查错误。sysctl选项kernel.kptr_restrict控制内核地址暴露限制:值"2"表示始终隐藏;“1"表示仅对具有CAP_SYSLOG能力的用户显示;“0"表示始终显示。问题在于仅依据kptr_restrict值决定是否显示地址,未验证用户是否具备CAP_SYSLOG能力。当kptr_restrict为1时,地址始终暴露,但实际上应对无CAP_SYSLOG能力的用户隐藏。该问题在提交b25a7c5af905中修复。

发现漏洞后,我们与Docker和Linux内核安全团队协调披露。Dominik最初通知Docker团队,认为漏洞源于Docker,同时报告了其他sysfs文件系统泄露(包括服务名称、容器ID和设备信息)。披露时间线见文末。

尽管多次请求更新未获Docker回应,Linux社区迅速修复了内核问题。KASLR绕过修复已回溯到多个Ubuntu LTS版本,但Docker的其他sysfs泄露未修复。Linux 4.19之前的内核版本仍易受KASLR绕过攻击。使用4.15内核的Ubuntu 18因未回溯修复仍存在漏洞。

无权限容器KASLR绕过披露时间线

  • 2020年6月6日:向Docker报告漏洞
  • 2020年6月11日:Docker回复可能通过"masked paths"功能屏蔽泄露信息的sysfs路径,建议内存地址泄露问题报告Linux内核开发者
  • 2020年6月11日:告知将联系security@kernel.org关于kASLR绕过
  • 2020年6月11-18日:深入分析kASLR绕过
  • 2020年6月18日:向security@kernel.org报告漏洞
  • 2020年6月18日:Kees Cook确认漏洞
  • 2020年6月19-21日:内核开发者讨论修补方案
  • 2020年6月30日:向Docker请求更新
  • 2020年7月3-14日:修复补丁并入Linux内核
  • 2020年7月11日:再次向Docker请求更新其他sysfs泄露,告知KASLR绕过已在Linux 4.19、5.4和5.7内核修复
  • 2020年12月3日:再次向Docker请求更新,告知拟公开披露问题。Docker未回复

2024年需要安全审计吗?

这两个漏洞差异显著:DoS问题涉及用户输入解析和解释,而内核漏洞是信息泄露(严格说是访问控制漏洞)。这种差异影响漏洞可检测性:引发DoS时会立即注意到服务可用性受损,而访问控制漏洞被利用时可能无法察觉。

可检测性差异对自动化测试至关重要。如Trail of Bits测试手册所示,模糊测试通常需要程序崩溃或挂起,因此我们主要在内存安全程序中发现DoS漏洞。通过模糊测试自动发现访问控制漏洞更具挑战性,需要实现模糊测试不变量。

安全审计与模糊测试同样是不可或缺的漏洞发现工具!我们的审计尽可能集成模糊测试,并寻找强制执行不变量的机会以捕获严重逻辑错误。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计