category
我们所有人都知道如果攻击者发现我们的用户凭据(电子邮件和密码)会发生什么:他们可以登录我们的帐户并造成严重破坏。 但是很多现代应用程序都在使用JSON Web令牌(JWT)来管理用户会话 - 如果JWT被泄露会发生什么? 由于越来越多的应用程序正在使用基于令牌的身份验证,因此这个问题与开发人员越来越相关,并且对于了解是否构建使用基于令牌的身份验证的任何类型的应用程序至关重要。
为了帮助完整地解释这些概念,我将向您介绍令牌是什么,它们如何被使用以及当它们被盗时会发生什么。 最后:如果你的令牌被盗,我会介绍你应该做什么,以及如何在将来防止这种情况。
这篇文章的灵感来自StackOverflow这个问题。 我对这个问题的回答已成为我迄今为止对StackOverflow最受欢迎的回复之一!
什么是令牌?
Web开发上下文中的标记只不过是表示会话的任意值。 标记可以是“abc123”之类的字符串,也可以是随机生成的ID,如“48ff796e-8c8a-46b9-9f25-f883c14734ea”。
令牌的目的是帮助服务器记住某人是谁。 以API服务为例:如果您有一个API密钥,可以让您通过服务器端应用程序与API服务进行通信,那么API密钥就是API服务用来“记住”您的身份的密钥,请查看您的帐户详细信息 ,并允许(或禁止)您提出请求。 在此示例中,您的API密钥是您的“令牌”,它允许您访问API。
然而,当大多数人今天谈论令牌时,他们实际上是指JWT(无论好坏)。
什么是JSON Web令牌(JWT)?
JSON Web令牌是特殊类型的令牌,其结构使得它们便于在Web上使用。 他们有一些定义特征:
- 它们表示为普通字符串。 这是一个真正的JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IlJhbmRhbGwgRGVnZ2VzIiwiaWF0IjoxNTE2MjM5MDIyfQ.sNMELyC8ohN8WF_WRnRtdHMItOVizcscPiWsQJX9hmw
因为JWT只是URL安全字符串,所以它们很容易通过URL参数等传递。
- 它们包含JSON编码的数据。这意味着您可以根据需要为JWT存储尽可能多的JSON数据,并且可以将令牌字符串解码为JSON对象。这使它们便于嵌入信息。
- 它们是加密签名的。了解它的工作原理本身就是一个主题。现在,只要知道这意味着拥有JWT的任何可信方都可以判断令牌是否已被修改或更改。这意味着,如果您的应用程序或API服务生成一个令牌,表明某人是“免费”用户,而某人稍后会更改令牌以表明他们是“管理员”用户,您将能够检测到并采取相应行动。此属性使JWT对于在难以获得信任的Web上的各方之间共享信息非常有用。
这是一个小代码片段,它使用njwt库在JavaScript中创建和验证JWT。这个例子纯粹是为了让您一眼就能看到如何创建JWT,在其中嵌入一些JSON数据并验证它。
const njwt = require("njwt");
const secureRandom = require("secure-random");
// This is a "secret key" that the creator of the JWT must keep private.
var key = secureRandom(256, { type: "Buffer" });
// This is the JSON data embedded in the token.
var claims = {
iss: "https://api.com",
sub: "someuserid",
scope: "freeUser",
favoriteColor: "black"
};
// Create a JWT
var jwt = njwt.create(claims, key);
// Log the JWT
console.log(jwt);
// Jwt {
// header: JwtHeader { typ: 'JWT', alg: 'HS256' },
// body:
// JwtBody {
// iss: 'https://api.com',
// sub: 'someuserid',
// scope: 'freeUser',
// favoriteColor: 'black',
// jti: '903c5447-ebfd-43e8-8f4d-b7cc5922f5ec',
// iat: 1528824349,
// exp: 1528827949 },
// signingKey: <Buffer 9c e9 48 a7 b3 c9 87 be 5f 59 90 a5 08 02 9b 98 5c 5e 1c 29 3f b0 33 c5 8c c8 f9 c8 3e 35 f0 7c 20 a0 aa 65 cc 98 47 b6 31 c5 5c d6 4e 6e 25 29 2b d3 ... > }
// The JWT in compacted form (ready for sending over the network)
var token = jwt.compact();
// Log the compacted JWT
console.log(jwt.compact());
// eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FwaS5jb20iLCJzdWIiOiJzb21ldXNlcmlkIiwic2NvcGUiOiJmcmVlVXNlciIsImZhdm9yaXRlQ29sb3IiOiJibGFjayIsImp0aSI6IjkwM2M1NDQ3LWViZmQtNDNlOC04ZjRkLWI3Y2M1OTIyZjVlYyIsImlhdCI6MTUyODgyNDM0OSwiZXhwIjoxNTI4ODI3OTQ5fQ.y7ad-nUsHAkI8a5bixYnr_v0vStRqnzsT4bbWGAM2vw
// Verify the JWT using the secret key
njwt.verify(token, key, (err, verifiedJwt) => {
if (err) throw err;
console.log("The JWT has been verified and can be trusted!");
// The JWT has been verified and can be trusted!
});
如何使用JSON Web令牌?
JWT通常用作Web应用程序,移动应用程序和API服务的会话标识符。但是,与传统会话标识符不同,传统会话标识符只是指向服务器端实际用户数据的指针,JWT通常直接包含用户数据。
JWT近年来变得流行的主要原因(自2014年以来仅存在)是它们可以包含任意JSON数据。 JWT相对于传统会话ID的好处是:
- JWT是无状态的,可以直接包含用户数据
- 因为JWT是无状态的,所以不需要实现服务器端会话(没有会话数据库,会话缓存等)
因为JWT是无状态的,所以当服务器端应用程序收到JWT时,它可以仅使用用于创建它的“密钥”来验证它 - 从而避免与后端数据库或缓存通信的性能损失,增加每个请求的延迟。
话虽如此,让我们来看看JWT通常如何在现代Web应用程序中使用。
- 客户端(通常是浏览器或移动客户端)将访问某种登录页面
- 客户端将其凭据发送到服务器端应用程序
- 服务器端应用程序将验证用户的凭据(通常是电子邮件地址和密码),然后生成包含用户信息的JWT。嵌入在JWT中的信息通常是:
- 用户的名字和姓氏
- 用户的电子邮件地址或用户名
- 用户的ID(如有必要,用于服务器端查找)
- 用户的权限(他们允许做什么?)
- 与正在使用的应用程序相关的任何其他数据
- 服务器端应用程序将此令牌返回给客户端
- 然后,客户端将存储此令牌,以便将来可以用它来标识自己。对于Web应用程序,这可能意味着客户端将令牌存储在HTML5本地存储中。对于服务器端API客户端,这可能意味着将令牌存储在磁盘或秘密存储中。
- 当客户端将来向服务器发出请求时,它会将JWT嵌入到HTTP Authorization标头中以标识自己
- 当服务器端应用程序收到新的传入请求时,它将检查是否存在HTTP Authorization标头,如果存在,它将解析标记并使用“密钥”验证它
- 最后,如果令牌有效并且循环将完成,则服务器端应用程序将处理请求
简而言之:JWT用于识别客户端。就客户而言,它们是王国的关键。
如果您的JSON Web令牌被盗,会发生什么?
简而言之:它很糟糕,真的很糟糕。
由于JWT用于识别客户端,如果其中一个被盗或受到攻击,攻击者可以完全访问用户的帐户,就像攻击者破坏用户的用户名和密码一样。
例如,如果攻击者获得了您的JWT,他们可以开始向服务器发送请求,将自己标识为您,并执行诸如进行服务更改,用户帐户更新等操作。一旦攻击者拥有您的JWT,就会结束游戏。
但是,有一件事使得被盗的JWT比被盗的用户名和密码稍微不那么糟糕:时机。由于JWT可以配置为在设定的时间(一分钟,一小时,一天等)后自动过期,因此攻击者只能使用您的JWT访问该服务,直到它过期。
从理论上讲,这听起来很棒,对吗?据称令牌认证的一种方式是使认证更加“安全”,这是通过短期令牌实现的。这是近年来基于令牌的身份验证真正起步的核心原因之一:您可以自动使令牌过期并降低依赖永久缓存的“无状态”令牌的风险。
毕竟,在安全领域,依靠缓存数据做出敏感决策,例如谁可以登录服务以及他们可以做什么被认为是一件坏事。因为令牌是无状态的并且允许比传统会话认证有一些速度改进,所以它们保持某种程度上“安全”的唯一方式是限制它们的寿命,以便它们在受到危害时不会造成太大的伤害。
这里唯一的问题是,如果攻击者首先能够窃取您的令牌,那么一旦获得新令牌,他们很可能会这样做。这种情况最常见的方式是通过中间人(MITM)连接或直接访问客户端或服务器。不幸的是,在这些情况下,即使是最短寿命的JWT也根本无法帮助你。
通常,令牌应被视为密码并受到保护。它们永远不应公开共享,并应保存在安全的数据存储中。对于基于浏览器的应用程序,这意味着永远不会将您的令牌存储在HTML5本地存储中,而是将令牌存储在JavaScript无法访问的服务器端cookie中。
通常,基于令牌的身份验证不会提供依赖于不透明会话标识符的典型基于会话的身份验证的任何额外安全性。虽然基于令牌的身份验证肯定有很多用例,但了解技术的工作原理以及弱点的位置至关重要。
另一个有趣的事情是,在某些情况下,被盗的JWT实际上可能比被盗的用户名和密码更糟糕。
让我们暂时假装您的用户名和密码已被盗用。在这种情况下,如果您登录的应用程序受多因素身份验证保护,则攻击者需要绕过其他身份验证机制才能访问您的帐户。
虽然猜测或暴力破解用户名和密码是一个非常现实的场景,但是能够危及用户的多因素身份验证设置可能非常困难。绕过基于应用程序的授权,短信验证,面部识别码,触摸ID等因素比猜测用户密码更具挑战性。
因此,受损的JWT实际上可能比受损的用户名和密码具有更大的安全风险。想象一下上面的场景,用户登录的应用程序受多因素身份验证的保护。一旦用户通过多因素登录并验证自己,就会为他们分配一个JWT来证明他们是谁。如果JWT被盗,攻击者不再需要直接绕过MFA(就像他们只有用户的用户名和密码一样) - 他们现在可以直接向用户发出请求而无需额外的身份证明。相当大的风险。
如果您的JWT被盗,该怎么办?
一旦JWT被盗,您将陷入困境:攻击者现在可以冒充客户并在未经客户同意的情况下访问您的服务。但是,即使你处境糟糕,你仍然需要充分利用它。
如果客户的令牌被盗,可以采取以下步骤。这些建议不适用于所有类型的应用,但应为您提供一些好主意,以帮助您从此安全事件中恢复:
- 立即撤销受损的令牌。如果您在服务器上使用撤销列表来使令牌无效,则撤消令牌可立即将攻击者从系统中启动,直到他们获得新令牌为止。虽然这是一个临时解决方案,但它会让攻击者的生活变得更加困难。
- 强制您的客户立即更改密码。在Web或移动应用程序的上下文中,强制您的用户立即重置其密码,最好通过某种多因素身份验证流程,如Okta提供的那样。如果攻击者试图使用受感染的令牌修改用户登录凭据,则强制用户更改其密码可能会使攻击者远离其帐户。通过要求多因素身份验证,您可以更自信地重置其凭据的用户是他们所声称的人而不是攻击者。
- 检查客户的环境。用户的手机是否被盗,以便攻击者可以访问预先认证的移动应用程序?客户端是否从受感染的设备(如移动电话或受感染的计算机)访问您的服务?发现攻击者如何获得令牌是完全理解错误的唯一方法。
- 检查您的服务器端环境。攻击者是否能够从您的角色中妥协令牌?如果是这样,这可能需要更多的工作来修复,但越早开始就越好。
一旦完成了这些步骤,您应该更好地了解令牌是如何被泄露的,以及需要采取哪些措施来防止令牌在未来发生。
如何检测令牌妥协
当令牌妥协确实发生时,它可能会导致重大问题。特别是如果您(作为服务提供商)无法快速检测到攻击者已经破坏了客户端的令牌。
如果您能够自动识别令牌被泄露的情况怎么办?这将极大地提高您服务的安全性,因为您可以主动防止可疑请求得到满足,从而保护您的服务和用户。
虽然不容易,但这绝对是可能的。像TensorFlow这样的现代机器学习工具包允许您构建功能(虽然复杂)的管道,以检测异常模式并主动负责这种情况。
例如,您可以使用机器学习来检测不寻常的客户端位置。假设您运行一个网站,并且您的用户已从旧金山登录并且已经提出了几个小时的请求。如果您发现请求在短时间内开始来自不同的地理区域,您可以立即阻止这些请求被执行,撤消令牌,并联系用户以重置其密码等。
以类似的方式,您可以使用机器学习来检测异常的客户端行为。如果令牌遭到入侵,攻击者很可能会采取措施以某种方式滥用您的服务。如果您的用户通常在您的网站上每分钟发出五个请求,但突然之间您会注意到用户每分钟发出50多个请求的大幅提升,这可能是攻击者获得保留的良好指标用户的令牌,因此您可以撤消令牌并联系用户以重置其密码。
通过机器学习进行模式检测和识别是处理这些更复杂问题的一种奇妙的现代方法。
这正是我们在Okta所做的 - 我们运行一个API服务,允许您在我们的服务中存储用户帐户,我们提供开发人员库来处理身份验证,授权,社交登录,单点登录,多因素等事务当用户登录由Okta提供支持的应用程序时,我们会分析一些数据点以检测帐户是否已被盗用,提示进行多因素身份验证,执行用户外展等。
积极主动地保护您的安全性有很多复杂性,但准备比准备好要好得多。
最新内容
- 7 hours ago
- 9 hours ago
- 9 hours ago
- 3 days ago
- 3 days 8 hours ago
- 3 days 8 hours ago
- 3 days 9 hours ago
- 3 days 9 hours ago
- 1 week ago
- 1 week ago