JSON网络令牌库中出现严重漏洞

怪狗 2016-8-1 Exploit 0 0

JSON网络令牌库中出现严重漏洞

如果你正在使用具有对称密钥(RS256、RS384、 RS512、 ES256、 ES384、ES512)的node-jsonwebtoken或pyjwt,请更新至最新版本。如果你正在使用带有对称密钥的php-jwt或者jsjwt,需要考虑使用其他不易受攻击的库,直到上述库被修复或验证。可参见jwt.io获取更多关于易受攻击库的信息。

最近,当我审查多个JSON 网络令牌执行的安全性时,我发现很多库中存在重要漏洞,允许攻击者绕过验证步骤。我在多个执行及语言中发现了两个相同的漏洞,因此我觉得有必要详细说明一下问题到底出在哪里。我认为修改标准能够帮助阻止未来漏洞的发生。

JSON 网络令牌是什么?

JSON 网络令牌(JWT)是一个带有某些数量要求的令牌创建标准。比如,一台服务器能够生成一个要求是“以管理员身份登录”并提供给客户端。客户端随后可利用这个令牌来证明他们确实以管理员身份登录。这些令牌被服务器的密钥签署,因此服务器可验证这个令牌是合法的。

JWT一般由三部分组成:一个头信息、一个有效负载、以及一个签名。头信息识别生成签名的算法,并查看如下一些信息:

JSON网络令牌库中出现严重漏洞

“HS256”说明这个令牌是通过HMAC-SHA256签名的。

有效负载包含我们希望作出的要求:

JSON网络令牌库中出现严重漏洞

如在JWT程控中说明的那样,我们包含一个叫iat的时间戳(也就是“发布时间(issed at)”的缩略语)。

这个签名是通过base64url计算的,对头信息及有效负载进行编码并以英文句点作为分隔符将它们连接在一起:

JSON网络令牌库中出现严重漏洞

base64url会对签名进行编码,并通过几个英文句点将这三部分连接起来:

JSON网络令牌库中出现严重漏洞

那么,错误出现在哪里?

首先,我们先来验证一个令牌。

第一步需要确认生成这个签名的算法是什么。没有问题,头信息中的alg字段给出了答案。

但我们还没有验证这个令牌,也就是说我们还没有验证这个头信息。这让我们陷入了一个尴尬的处境:为了验证这个令牌,不得不允许攻击者选出我们验证这个签名所使用的方法。

对于一些执行来说,这会产生灾难性后果。

“none”算法

None算法是JWT的一个奇怪客人。本来只有在令牌真实性已被验证的情况下才能使用这个算法。但它是强制执行的仅有的两个算法之一(另外一个是HS256)。

很遗憾,一些库将通过none算法签名的库当做拥有已验证签名的合法令牌。结果,任何人都可以创建“已被签名的”令牌,不管他们想要多少有效负载,这就导致任意账户可访问某些系统。

组合这样一个令牌并非难事。将上述示例头信息修改成包含alg、none而非HS256就可以。对有效负载进行一些必要修改。使用空签名(也就是signature=””)。

现在,多数(希望是全部)执行都会进行基本检查以避免受到攻击:如果密钥已提供,那么令牌验证就会因为使用none算法而失败。但是它并没有解决根本问题:攻击者会控制算法的选择。我们再深挖一下。

RSA还是HMAC?

JWT程控同时还定义了很多非对称性签名算法(基于RSA及ECDSA)。这些算法会创建令牌并通过一个私钥签名,但需要通过一个公钥验证。也就是说,如果你公布了这个公钥但自己拥有私钥,只有你能签名这些令牌,但如果已有令牌被正确签名,那么任何人都可以查看。

我查看的多数JWT库都有一个如下API:

JSON网络令牌库中出现严重漏洞

在使用HMAC签名的系统中,verificationKey将会是服务器的秘密签名密钥(因为HMAC使用相同的密钥进行签名及验证):

JSON网络令牌库中出现严重漏洞

在使用费对称算法的系统中,verificationKey会成为公钥,令牌应被验证:

JSON网络令牌库中出现严重漏洞

遗憾的是,攻击者可予以滥用。如果一台服务器需要RSA签名的令牌但实际上接收到的是HMAC签名的令牌,它会认为公钥实际上是一个HMAC密钥。

为什么说它是一个灾难呢?HMAC密钥理应是私密性的,而公钥是公开的。也就是说攻击者有访问公钥的权限,而且可以利用公钥来伪造一个服务器会接受的令牌。

要想实现非常容易。首先,抓取你最喜欢的JWT库,为令牌选择一个有效负载。然后,将服务器利用的公钥当做验证密钥(很可能是基于文本的PEM格式)。最后,用PEM格式的公钥签名令牌作为HMAC密钥。也就是说:

JSON网络令牌库中出现严重漏洞

最狡猾的一步是确保serverRSAPublicKey与服务器中使用的验证密钥相似。这些字符必须与攻击完全匹配——格式完全一样、没有多余或漏掉的换行符。

结果,所有了解公钥的人都能够伪造将会通过验证的令牌。

对库开发人员的建议

我建议JWT库在验证函数中添加一个algorithm参数:

JSON网络令牌库中出现严重漏洞

服务器应该已经知道它签署令牌的算法是什么了,而且允许攻击者提供值是不安全的。

一些人可能认为由于兼容性的问题,一些服务器需要支持多个算法。在这种情况下,单独的密钥能够(而且应该)用于每个被支持的算法。为此,JWT专门提供了一个“密钥ID”字段(kid)。由于服务器可通过这个密钥ID来查看密钥机器相应的算法,攻击者再也无法控制用于验证的密钥了。在任何情况下,我觉得JWT库都不应该在头信息中查看alg字段,除非查看它是否与所期待的算法匹配。

所有使用JWT执行的人都应该确保拒绝不同签名类型的令牌。一些库拥有白名单或黑名单算法的可选机制;你需要将这些机制用起来以免带来风险。如果你能这样做就更好了:在所有用于完成重要任务的开源库中制定开展安全审计的政策。

改进JWT/JWS标准

我提议否掉头信息中的alg字段。如我们所见,滥用这个字段会对JWT/JWS执行的安全性产生毁灭性影响。就目前来看,密钥ID是一种合适的替换方式。这保证了对程控的变化:由于对alg的依赖性,JWT库会继续通过安全漏洞编写。

JWT(以及JOSE)为安全加密技术实现提供了跨平台机会。通过这些修复,希望我们会离这个理想更近一步。

本文由 360安全播报 翻译,转载请注明“转自360安全播报”,并附上链接。
原文链接:https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/

原文地址:https://www.77169.com/exploits/2015/20150401164547.shtm

转载请注明来自华盟网,本文标题:《JSON网络令牌库中出现严重漏洞》

喜欢 (0) 发布评论