在为上一篇博客收集一些信息时,我发现了一个有趣的JSON Web 签名 (JWS)标头:https://trustedsec.com/blog/attacking-jwt-with-self-signed-claims,想进一步了解它。RFC 7515 第 4.1 节列出了已注册的标头参数。这次,x5u和x5c标头引起了我的注意。这两个标头使用 X.509 证书,并定义了用于验证 JWS 完整性的公钥存储位置。
对于这两个标头,攻击者可以使用自己的私钥对令牌进行签名,并修改标头值以指定用于签名验证的公钥。此时,攻击者将拥有修改令牌声明的完全访问权限,并且服务器将接受这些信息。虽然这并非一种新的攻击方式,但我找不到任何 Burp 扩展程序可以让我轻松利用此漏洞。在本篇博文中,我将带您详细了解攻击过程,并演示我为利用这些标头而构建的 Burp Suite 扩展程序。
1.1 设置
要开始此攻击,我们需要一个易受攻击的应用程序进行测试。为此,我在 Flask 中创建了一个易受攻击的 API。
https://github.com/Tsynack/JWT_X509_Re-Signer/tree/main/Example%20API
图 1 - 运行示例 API
为了简化测试,我还构建了一个自定义的 Burp 扩展,允许修改标头和声明。该扩展还可用于重新签名令牌。您可以在此处找到该扩展:
https://github.com/Tsynack/JWT_X509_Re-Signer/tree/main/Burp%20Extension
注意:该扩展依赖于 Burp 扩展设置中设置的 Jython。
要安装扩展,请导航至扩展>添加>扩展类型:Python>并选择JWT_x509_Re-Sign.py文件。
图 2 - 加载 JWT 重签名器
一旦扩展被加载,任何在 Burp 的 HTTP 历史记录或中继器中包含 JWS 的请求都应该有一个标记为“重新签署 JWT”的选项卡。
图 3 - 已安装扩展
为了执行此攻击,我们最后需要的是用于签名令牌的 X.509 私钥以及相关证书,以便服务器可以验证签名。使用 OpenSSL,可以通过以下命令完成此操作。
opensslreq-newkeyrsa:2048-nodes-keyoutprivate_key.pem-x509-days 365 -outcert.pem
1.2 攻击剖析
快速回顾一下,JWS 包含三 (3) 个部分:
-
标头- 包含有关如何生成签名的详细信息,并且可能包含有关 JWS 内容的详细信息
-
声明- 包含已发生的身份验证过程的详细信息。以下是一些声明示例:
-
Iat(发布时间)- JWS 生成的纪元时间
-
Exp(到期)- 服务器不再接受令牌的纪元时间
-
Sub(主题)——与令牌关联的用户
-
签名- 声明用于结合标头中列出的算法生成签名。这可确保令牌在服务器处理请求之前未被篡改。
图 4 - 代币结构示例
图 5 - 示例标题
图 6 - 索赔示例
在 JWS 的 RFC 中,概述了两 (2) 个可选标头参数:
-
x5c - 包含 X.509 公钥证书或证书链
-
x5u - 指向 X.509 公钥证书或证书链的 URI。
公钥是服务器验证令牌签名并确定声明是否被篡改的工具。如果服务器使用这些参数的值来验证签名,我们就有机会修改声明并使用自己的密钥对令牌进行签名。
1.3 概念验证
使用前面提到的示例 API,我们将向 Burp 的中继器发送几个请求来篡改令牌。在示例 API 文件夹中,我包含了一个API_example_requests.txt文件,其中包含用于生成登录和验证请求的 curl 命令。您应该能够复制并粘贴登录命令,并在响应中收到令牌。令牌需要复制到验证命令中。
图 7 - API 登录
如果一切正常,Burp 的代理历史记录中应该会记录这两个请求。右键单击/verify请求并将其发送到中继器。
在中继器中,导航到“重新签名 JWT”选项卡。按下“解码”按钮将对令牌标头和声明进行 Base64 解码。对这些值的任何修改都将在令牌重新签名后生效。首先将sub声明的值修改为root。
图 9 - 解码和修改声明
对于第一次攻击,我们将公钥证书直接嵌入到 x5c 参数中。为此,您需要导入之前使用 OpenSSL 生成的 X.509 私钥和证书。
图 10-导入私钥和证书
由于我们将证书嵌入到令牌中,因此请选择使用x5c 标头重新签名令牌,然后单击“攻击”!请求中的令牌将自动使用新签名的令牌进行更新。发送请求应该会返回200 OK,表示更新后的令牌已被服务器接受。
图 11 - 服务器接受重新签名的令牌
如果您已经做到了这一步,那么恭喜您通过使用自己的私钥对令牌进行签名来利用它!
1.4 攻击 x5u
x5u 标头并非将证书内容直接嵌入到令牌中,而是将服务器指向一个 URI,以便找到证书内容。为了利用这一点,我已将cert.pem托管在我的 Web 服务器上,并将把 URL 添加到我们扩展程序中的相应字段。
确保将我们用于重新签名的方法更新为x5u 标头,然后单击“攻击”!发送请求后,托管证书的 Web 服务器应该会收到cert.pem的请求,这表明 API 在验证签名时已发出请求。
图 12 - 显示外部交互的访问日志
API 响应应显示 200 OK,表明签名和声明已被接受。
图 13 - 利用 x5u 标头
1.5 结论
对于每个已识别的标头,问题在于服务器信任提供的证书来验证令牌签名。作为攻击者,我们可以控制标头的值,从而提供我们自己的证书。最终结果是令牌被盗用,任何人都可以更改声明中的值,从而冒充其他用户或执行权限提升。
作为开发者,请检查令牌的验证流程。即使您在颁发令牌时未明确使用这些标头,服务器是否会接受标头值并根据提供的证书验证签名?请编写代码,确保仅使用预期的证书来验证令牌签名。
原文始发于微信公众号(Ots安全):使用 X509 证书攻击 JWT
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论