如何使用被盗令牌防止 Rest Web 服务身份验证
Posted
技术标签:
【中文标题】如何使用被盗令牌防止 Rest Web 服务身份验证【英文标题】:How to prevent Rest web-service Authentication with stolen Token 【发布时间】:2020-05-23 11:44:57 【问题描述】:众所周知,Rest 服务是无状态的,一般的身份验证策略是使用基于令牌的身份验证。
在登录服务中,它需要返回令牌的凭据。
此令牌可能设置在客户端cookies中,所有后续请求都使用此令牌进行验证,如果令牌有效则处理新请求。
现在我的问题是如何验证令牌?如果有人窃取了令牌并试图通过仅编辑 cookie 来使用窃取的令牌访问其余服务,那么如何识别和限制它?
我们永远无法知道令牌是否由有效用户获取,并且同一用户正在尝试访问后续请求。但是有哪些可能的方法让它变得更加困难,比如验证请求是否来自同一来源?
一个普遍的建议是为令牌/cookies设置老化,但直到令牌/cookies的年龄仍然没有帮助。
任何建议将不胜感激。
【问题讨论】:
这里的威胁模型是什么?令牌如何被盗然后被滥用? @root 令牌存储在客户端 cookie 中,通过浏览器使用的某些其他网站可能会获取该 cookie。 浏览器不允许任何站点访问来自任何其他站点的 cookie。要窃取 cookie,您需要更重要的东西,例如持久性 XSS。 【参考方案1】:我不相信有任何 100% 万无一失的方法来防止使用被盗用户令牌进行访问。你怎么知道令牌被盗了?但从我的脑海中,您可能需要考虑以下几点:
-
使用相同的令牌但不同的用户代理访问 REST 服务是可疑的。这可以通过 User-Agent 标头的值来识别。您可能需要考虑放弃此类请求。
如果 IP 地址更改但令牌仍然相同怎么办?好吧,也许有人正在使用负载平衡器并通过不同的 IP 地址访问网络?还是他使用与以前相同的令牌/cookie 访问了 ***?如果您对丢弃此类请求不感到内疚,您也可以通过检查源 IP 地址来提高安全性。
如果是 JWT 令牌,您将需要一些基础设施来处理黑名单。关注this。
【讨论】:
在英国,知名 ISP 频繁更改用户 IP 地址 - 平衡安全性与用户体验 在到期时分配赏金,这个答案更相关,但我们已经实施了适当的解决方案。我在回答中也解释过。【参考方案2】:我目前对在浏览器中授权请求的“最安全”方法的理解是要求组合验证 HttpOnly SameSite cookie 和 HTTP 标头(例如 Authorization
或 X-CSRF-Token
)。
例如,在向浏览器发出 JWT 时,将 JWT 签名发送到 HttpOnly SameSite
cookie 中,并将正文(不带签名)发送到客户端以存储在 localStorage
中并在 Authorization
标头中提交.授权请求时,将两者组合回完整的 JWT,然后正常验证。
或者,您可以生成两个带有字段的 JWT 来区分它们(例如,客户端包含 "browser"
,cookie 包含 "cookie"
)并要求两者都有效并且都标识同一用户。一个在Authorization
标头中发送并存储在localStorage
中,另一个使用SameSite HttpOnly
cookie。
另一种流行的方法是将 CSRF 令牌存储在 JWT 的字段中,并将 JWT 放入 cookie 并要求客户端在标头中发送匹配的令牌(例如X-CSRF-Token
)。
所有的解决方案都有效地阻止了XSS和CSRF攻击:XSS无法检索HttpOnly cookie,CSRF不包含HTTP头,所以这两种攻击都被阻止了。
请注意,您可能只想将此规则应用于来自网络浏览器的请求。对于服务器到服务器的通信,请求不受 CSRF 和 XSS 攻击。
【讨论】:
【参考方案3】:您可以使用 jwt 是一种 Internet 标准,用于创建基于 JSON 的访问令牌,这些令牌断言一定数量的声明。例如,服务器可以生成具有“以管理员身份登录”声明的令牌并将其提供给客户端。然后,客户端可以使用该令牌来证明它以 admin 身份登录。
它是如何工作的?
首先它包含开发者生成的私钥:
让我们有这个密钥 :sfcqw@sav%$#fvcxv*s_s515
和这个称为私钥的密钥,我们还有一个公钥,这个公钥生成取决于用户数据和私钥,如果你不知道它包含什么是不可能的'不知道私钥。
更多解释:
公钥:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.plpJkAcgrgCIsoRyV2kjGsvWF6OsXU1mD785OSWTH4o
我们有我们的私钥生成的上述密钥:sfcqw@sav%$#fvcxv*s_s515
要更清楚地访问这个网站:https://jwt.io/ 并尝试通过公钥而不像图片那样放置密钥,你会明白一切。
【讨论】:
【参考方案4】:通过各种方法苦苦挣扎后,我们找到了以下解释的解决方案:
-
我们在登录请求时将令牌(加密)存储在 cookie 中,并且对于每个后续请求,此 cookie 都会得到验证。
问题是如果有人将 cookie 中的令牌替换为另一个有效令牌,因为 cookie 由客户端浏览器维护。
解决方案 :-> 虽然令牌值是加密的,但它只代表一个值,因此如果将整个加密值替换为另一个有效的加密值,它可能会被黑客入侵。
所以为了解决这个问题,我们添加了另一个 cookie,它是多个值的组合。
例如
Cookie 1 -> 加密令牌
Cookie 2 -> 包含用户名等信息的加密对象 + 一些其他用户上下文详细信息 + 令牌
因此,在 Cookie 1 的情况下,很容易用另一个加密值替换,因为尽管它已加密,但它只代表一个令牌。
但在 Cookie 2 的情况下,它包含具有多个值的对象,因此只能在同一个 cookie 中修改、加密和设置令牌值。
在身份验证之前,我们正在解密整个 cookie 2,从中获取令牌部分并根据 cookie 1 验证其中的令牌部分。
这解决了我们的问题!!
感谢大家的时间和指导。
【讨论】:
【参考方案5】:对我来说,没有办法防止访问被盗 JWT 令牌,除了
为令牌设置短暂的超时 通过只允许特定的`User-Agent. See more 通过自定义组织的标头键在 HTTP 请求级别更安全,例如My-X-Auth = Bearer <token>
而不是 Authorization= Bearer <token>
通过限制受信任的 url/域,在 HTTP 请求级别更安全,例如 X-Content-Security-Policy
。 See more
【讨论】:
以上是关于如何使用被盗令牌防止 Rest Web 服务身份验证的主要内容,如果未能解决你的问题,请参考以下文章
会话管理:如何为 REST 服务生成身份验证令牌? (球衣)
Rest Web 服务:具有令牌安全性的匿名和经过身份验证的用户