分析 JSON Web 令牌面临的失效用户身份验证威胁
执行摘要
Akamai 研究人员对 JSON Web 令牌 (JWT) 进行了分析并揭示了发生 JWT 威胁和趋势的不同场景。这些令牌是一种用于失效用户身份验证攻击的媒介,而这些攻击位列开放 Web 应用程序安全项目 (OWASP) API 安全十大漏洞之一。
JWT 负责颁发令牌(通常在客户端和服务器之间)来对用户进行安全验证,从而保护 API。这些令牌是最常见的验证形式之一,它们包含将以 JSON 对象形式共享的信息。
虽然每个令牌都未进行加密,但它经过了编码并且具有验证签名。在对 JWT 的很多威胁中,一部分威胁是由于不正确实施或低熵短密钥造成的,我们对这些威胁进行了研究。
帐户接管、特权提升和数据泄露是 JWT 用户和企业在选择 JWT 作为 API 中的首选令牌时所面对的三大潜在风险。我们在流量中观察到,即使对称算法在理论上具有较低安全性,大多数 JWT 仍然使用该算法。
在本博文中,我们提供了有关如何应对这些 JWT 威胁的最佳实践。
前言
JWT 是广泛使用且相对易于实施的令牌架构,但潜藏着很多风险。在实施和保护 JWT 时,必须考虑这些风险。对于 JWT,其中一个最严重的风险位列 OWASP API 安全十大漏洞之一,它就是失效的用户身份验证。
当 API 未正确验证发出请求的用户的凭据和身份时,就会发生失效的用户身份验证。很遗憾,这对 JWT 来说是一种常见漏洞,可能会导致攻击者冒充或访问另一个用户的帐户,从而造成特权提升和数据泄露。
保护管道
JWT 是 API 和 Web 应用程序中一种常用的身份验证令牌。我们在流量中观察到,Web 应用程序现在采用更多的 API 并将它们公开给客户,这会增加不同 API 端点中对无缝身份验证的需求。
API 是企业的主管道,用于承载身份验证和授权机制、查询数据库以及公开企业的大多数函数。出于此原因,在 API 领域中 JWT 威胁更危险。在本博文中,我们将介绍 JWT 基础知识、JWT 面临的六大威胁以及如何应对这些威胁。
JWT 基础知识
JWT 是一种用于发送签名 JSON 数据,以便在 Web 应用程序、移动应用程序和 API 中传输数据的格式,通常仅用于身份验证。JWT 由三部分构成:标头(也称为 JOSE 标头)、有效负载和签名,它们用点分隔(图 1)。
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIiLCJpYXQiOjE2NzYyMTc5NTAsImV4cCI6MTcwNzc1Mzk1MCwiYXVkIjoiYWthbWFpLWJsb2ciLCJzdWIiOiIiLCJjb21wYW55IjoiQWthbWFpIiwidXNlciI6IkFrYW1haS1yZWFkZXIiLCJhZG1pbiI6Im5vIn0.kMPz3Z7BSlBTJKijD8bcrpzTZejX7VCZ77w5oQwJO6I
图 1:这是 JWT 中三部分的示例
标头和有效负载
标头和有效负载都采用 Base64 URL 安全编码, 是 IETF 指定 用于字段的建议字符串(图 2)。“已编码”表示它们无法由人眼直接读取,但可以轻松地由服务器进行解码。这样做的目的是确保数据的完整性和可用性,同时确保它是“URL 安全的”。通过这种方式,它不会包含网络浏览器所使用的重叠字符。
JOSE 标头用于 JWT 和 JSON Web 加密 (JWE),从本质上说后者是有助于避免最常见 JWT 攻击的加密 JWT。用于指定所选令牌方法的字段为“typ”(typ:JWT/JWE)。有效负载可以包含注册字段(由互联网号码分配局声明)或自定义字段,具体取决于实施。
图 2:已编码的 JWT
签名
签名用于验证令牌,这表示服务器生成了令牌并且数据在此令牌创建后未发生更改。
创建签名有两个主要步骤:
对用点分隔的标头和有效负载应用加密算法(例如,MAC),该算法使用密钥
对已加密的标头和有效负载应用哈希算法(例如,SHA256)
如果使用 JWT,服务器会对签名进行验证,以验证令牌本身。(稍后,我将介绍用于验证的不同算法。)
JWT 在 Web 应用程序中广泛用于身份验证,不仅因为它们易于使用(可以大规模使用)并且易于实施,还因为服务器所需的数据保存在客户端。但是,即便 JWT 已签名,仍然存在与之关联的风险。JWT 使用纯文本,并且每次实施都由不同的有效负载字段组成。因此,攻击面很广并且出错几率很大。
通过探究 JWT 所面临的一些更常见且有意思的威胁,我们可以更加了解漏洞,更轻松地检测到恶意行为,更好地抵御风险,并且可以制定必要的安全措施来防范潜在漏洞。
我们的目标是,为用户提供一种更安全的方法来使用 JWT,并且向安全专业人士和管理员提供有助于他们履行职责所必需的工具和建议。
对 JWT 的六大威胁
1.允许服务器使用未验证的令牌
由于 JWT 经过了签名但未进行加密,因此必须在使用前进行验证。在大多数基本威胁场景中,应用程序根本不进行验证,攻击者可以编辑有效负载(例如, 特权提升)并且不更改签名,甚至可以将其删除并获取更高权限。
另一种方法是在标头中使用“alg”参数,此参数表示已用于对令牌进行签名的算法。“None”是一个合法值(并且 JWT 被称为不安全的 JWT),因此任何人都可以很容易地对令牌进行签名。在后端,也存在一种可能的 JWT 验证实施。
此方法从在标头中查找“alg”字段开始。然后,使用指定的算法对令牌进行验证。“None”算法表示不需要对该令牌进行签名和验证。编辑令牌的有效负载、标头(修改为 alg:none),“自签名”(删除签名)将使攻击者成功实施攻击。
示例
图 3 显示了已解码 JWT 的示例。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiZXhhbXBsZSBuYW1lIiwiaWF0Ij
oxNjU5MjM5MDIyfQ.PrhAp2DUWXoL01_odyLATuzrwn5rMtY1IVsP8y4LH5E
decoded:
{
"alg": "HS256",
"typ": "JWT"
}
.{
"name": "example name",
"iat": 1659239022
}
图 3:已解码 JWT 的示例
我们假设 API 端点在有效负载中使用“alg”字段作为选定的验证算法。
但我们想编辑 JWT(图 4)。通过这种方式,我们成功地伪造了另一位用户的有效 JWT。
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJuYW1lIjoiZXhhbXBsZSBuYW1lIiwiaWF0Ijo
xNjU5MjM5MDIyfQ.
decoded:
{
"alg": "none",
"typ": "JWT"
}
.{
"name": "other person's name",
"iat": 1659239022
}
图 4:已编辑为使用 alg:none 的 JWT。
最佳实践:这很简单: 始终 使用经过硬编码的预定义算法来进行验证,然后再使用令牌。请勿使用 alg 参数作为验证算法的指针。
2.将同一私钥用于不同的应用程序
有很多公司选择对不同的应用程序进行单独注册。使用同一私钥将在两个应用程序中创建一个有效令牌,但具有不同的用户 ID。在这种情况下,问题在于使用第一个应用程序的令牌对另一个应用程序发出请求,以及 接管帐户 (而不在于您的选择)(图 5)。
最佳实践:以下是另一条简单的经验法则:在分隔用户 ID 时,使用不同的私钥。
3.使用弱签名算法
有两种主要的算法系列:对称 (HSXXX) 和非对称(RSXXX、ESXXX、PSXXX)。对称算法需要一个共享密钥;非对称算法需要私钥和公钥(表 1)。
对称 |
|||
---|---|---|---|
HSXXX |
HMAC + SHA |
相对较弱的算法 |
使用共享密钥 |
非对称 |
|||
RSXXX |
RSA + SHA |
更安全的算法 |
使用私钥和公钥 |
ESXXX |
ECDSA + SHA |
三者中最安全的算法 |
使用私钥和公钥 |
表 1:两种主要的算法系列
从攻击者的角度来看,对称算法更容易进行暴力破解,无需收集公钥并且尽可能地高效利用计算时间。我们在流量中观察到,对称算法比非对称算法使用更广泛(图 6)。
理论上,对称算法需要的计算量更少,因此在大规模使用的情况下,它们可能比非对称算法的表现更好。
最佳实践:使用非对称算法。我们建议使用 ECDSA 算法,从密码学上来说这是目前最安全的选择。如果密钥具有高熵并且足够长,那么保护措施得当的对称密钥是可接受的。
4.选择较短并且/或者低熵的私钥
攻击者能够以低成本快速暴力破解较短并且/或者低熵的私钥。有一种易于使用的破解软件,可以安装在配备图形处理单元 (GPU) 的高性能云环境中。GPU 性能得到了快速提升,这对破解能力也产生了影响。现在的高端图形卡的破解速度几乎是三年前的 2.5 倍。
表 2 中显示了三年前和现在破解一个八字符私钥(不考虑其熵)所需要的天数对比结果。
高端图形卡 |
破解天数 |
---|---|
三年前 |
10.5 天 |
现在 |
4.5 天 |
表 2:破解一个八字符私钥所需要的天数
一个几年前需要大约 24 小时才能破解的七字符私钥如今只需要不到 90 分钟即可破解。此攻击的独特之处在于,它离线运行而不会触发企业的防御措施,甚至您都不知道自己正在遭受此类攻击。
假设您是由国家扶持的攻击者,并且将创建一个用于该攻击的编排系统。拥有 JWT 的私钥意味着攻击者能够伪造签名令牌,并且只需要知道任何其他用户的 ID 便可冒充该用户。
最佳实践:选择一个高熵的长私钥(至少包含 10 个字符)。我们建议使用 RSA 作为密钥生成器。
5.在 JWT 的有效负载中存放敏感数据
JWT 采用 Base64 URL 编码,因此有效负载未经过加密。存储 DB 名称、增量式 ID(任何类型)或任何服务器内部字段和数据都会导致过度数据暴露,这可能会给采用其他攻击媒介(例如,失效的对象级别授权)的攻击者提供帮助。
最佳实践:请勿在 JWT 中存储敏感数据。如果您需要存储敏感数据,请使用 JWE。
6.密钥混淆
使用非对称算法时,私钥用于生成 JWT(签名部分),而公钥用于验证该 JWT。攻击者可以将标头中指定的算法改为对称算法(例如,HS256),并使用服务器用于验证的合法公钥创建签名。
在这种情况下,未正确实施的后端将使用该公钥并运行攻击者在标头中的指定的对称算法,从而成功验证该攻击者伪造的 JWT。
示例
图 7 显示了服务器生成新 JWT 的过程,图 8 说明了服务器的 JWT 验证过程。
在验证的最后一个部分中,进行比较时会发生抛出错误,其原因是以下两者之一(或两者都有):
标头和有效负载已经过编辑,但签名未经过编辑
正确算法或正确密钥的配置错误
图 9 显示了密钥混淆攻击。
最后一步:服务器将使用图 8 中说明的过程来验证令牌,在此过程中服务器信任 alg 字段。它使用公钥作为密钥,运行 HS256 算法来验证令牌,而这正是攻击者所计划的。
最佳实践:在验证过程中使用预定义的算法,而不要信任用户输入的内容。
结论
JWT 是最常见的身份验证令牌。在经过身份验证后,它支持使用很多 Web 应用程序和 API,而不必频繁登录。但是,JWT 带来了很多威胁,因为它们既没有进行加密,在实施过程中也未考虑到安全性。
计算机的性能现在得到了快速提升,这导致弱密钥面临各种风险,在几天而不是几年之内就能够被破解。如果企业使用的是 JWT,那么此类攻击可以在企业不知不觉的情况下离线运行。
对称算法是最常见的算法类型,这使攻击者能够更轻松地实施攻击。
另外,还有更复杂的威胁(例如,身份验证攻击),但攻击者难以自动实施身份验证攻击。但是,简单的 JWT 攻击媒介可以实现自动化并被大规模利用。
出于这些原因(以及很多其他原因),用户务必要了解 JWT 的漏洞以及为防范潜在漏洞而实施的最佳安全实践。我们希望本文中的分析能够在保护 JWT 免受失效用户身份验证(OWASP API 安全十大主要威胁之一)的影响时提供便利。