【问题标题】:JWT Token and CSRFJWT 代币和 CSRF
【发布时间】:2018-05-02 14:59:55
【问题描述】:

我仍然不清楚 JWT 和 CSRF 是否一起工作。我了解 JWT 的基础知识(它是什么以及它是如何工作的)。我也理解与会话一起使用时的 CSRF。同样,我知道将 JWT 存储在 localStorage 中存在风险,这就是您需要 csrf 令牌的原因。所以我的问题是,我如何同时使用它们。为简单起见,假设我有一个登录页面。

1) 我让用户登录,如果用户通过身份验证,一旦使用了电子邮件和密码,服务器将发送一个 CSRF 并将使用 JWT 存储一个 httpOnly cookie(如何使用 PHP 设置 cookie)。我的理解是您可以使用header('Set-Cookie: X-Auth-Token=token_value; Secure; HttpOnly;');请确认是否可以这样做。

2) 一旦我用 JWT 设置了 cookie。我如何通过后续请求发送 CSRF 令牌> 据我了解,您将它们设置在标头中。因此,如果我发出 Ajax 请求,我会将它们放在标题中。

3) 一旦发出请求并且 CSRF 令牌与请求一起发送。验证是如何进行的。我在比较什么?

最后,实施起来安全吗?

如果您能提供尽可能多的细节,我将不胜感激。

【问题讨论】:

    标签: javascript php http jwt


    【解决方案1】:

    防御 CSRF 的通用范式是为每个“表单”生成一个令牌,并验证为特定表单设置的令牌是否正确。

    这样,攻击者无法猜测令牌,因此可以制作一个外部表单发送到您的服务器。

    通常,设置该令牌的方法是通过Cookie,客户端应用程序会将其附加到一些自定义标头,这将为您提供额外的保护,然后,服务器应比较 cookie 值和标头值.

    令牌仅对一个会话有效是重要,否则,攻击者可以重用他在攻击向量中获得的相同令牌。

    JWT,是一种向系统验证用户身份的方法,而不是验证请求是否有效。

    我将尝试通过示例进行解释,假设您没有实施任何针对 CSRF 的保护,但您确实有一种机制来验证您的用户(使用 JWT),因此用户使用正确的用户登录 &通过,你的服务器会发送一个 JWT,客户端会将它保存到 localStorage/memory。 现在,攻击者可以在他的网站上制作一个指向您的服务器的表单,假设他知道用户的 JWT 令牌(他通过 MITM 等其他方法获得),他需要做的就是欺骗用户进入他的带有表单的页面,如果有任何问题,表单将发送给您,您的服务器将接受请求并且攻击将成功。

    如果你实现了任何 CSRF 机制,示例中的攻击者将无法猜测当前令牌,因此你的服务器将忽略他的请求。

    【讨论】:

    • 我理解认证和授权的区别。我的问题是如何做到这一点,换句话说,我到底在比较什么。我完全理解这些概念!
    • 为了添加 CSRF,正如我所写的,您应该通过 Cookie 传递一个令牌,客户端应用程序会将其作为隐藏字段附加到表单或通过标头附加到 ajax 请求。然后你可以在服务器端比较cookie中的token在附加字段(或标头)中具有相同的值。
    • 这是倒退的。你不会受到 csrf id 的影响,你将令牌存储在本地存储中。如果您将令牌存储在 cookie 中并将其用作身份验证,因为它会自动添加到 req。您应该添加 csrf 保护作为标头,因为攻击者无法自动添加自定义标头
    • 你是对的,基本上,只要你只使用 cookie 来验证用户,你就容易受到 CSRF 的攻击。如果作为标头发送,则使用 JWT 可以防止 CSRF 攻击
    • 也许你应该专注于使用网络工作者安全地存储你的 jwt 令牌
    【解决方案2】:

    我自己看到并使用过的一种方法是将 CSRF 令牌作为声明包含在 JWT 中。所以当用户发送用户名和密码时,你可以这样做:

    1. 如果用户名和密码正确,请继续以下列表。
    2. 创建一个新的 JWT 并将生成的 CSRF 令牌作为声明包含在负载中,然后签署 JWT。
    3. 通过设置包含 JWT 的 HTTPOnly cookie 来响应客户端的身份验证请求。这确保只有浏览器(不是客户端应用程序和可能的恶意脚本)可以访问 JWT。将 cookie 设置为 secure 也是一个好主意。如果使用不安全的通信渠道(即不是 https),这将阻止浏览器发送 cookie。
    4. 在设置 JWT cookie 时,您还应该设置一个 HTTP 标头,该标头也将包含您生成的 CSRF 令牌。请注意,现在您将在两个地方拥有 CSRF 令牌 - 在 JWT cookie 内和 HTTP 标头中。
    5. 在您的客户端应用程序中,将 CSRF 令牌从标头存储到本地存储中。
    6. 对于每个请求,从 localstorage 获取 CSRF 令牌并将其作为请求标头包含(包含 JWT 的 cookie 由浏览器自动传递)。
    7. 服务器应从 cookie 中读取 JWT,验证其签名并从 JWT 的负载中读取 CSRF 令牌。然后它应该将它与请求标头中的 CSRF 令牌进行比较。如果它们匹配,服务器可以继续处理请求。

    我建议您观看 this 谈论 JWT。它详细介绍了相同的方法(也有漂亮的图表)。随意观看整个演讲,或者如果您对 CSRF 特别感兴趣,请从 36:29 开始。

    下面是一张幻灯片(来自上面链接的演示文稿),演示了如何一起使用 JWT 和 CSRF 令牌。我用与上面列表相对应的红色数字对其进行了注释。

    【讨论】:

    • 你能澄清一下#4。当您在同一个响应中说时,您的意思是向客户端回显或将其设置在标头中?
    • @Gacci 在标题中设置
    • 我很抱歉。我仍然很困惑。是标题#3 的#4 部分中的标题。两者都一样吗?我的理解是,您设置了两个 cookie,一个带有 JWT(安全和 HttpOnly),另一个 cookie(仅安全)。然后将仅安全 cookie 存储在 localStorage 中,然后与 jwt 中的 cookie 进行比较。对吗?
    • 编辑了我的答案。在 #3 中,您设置了一个 HTTPOnly 安全 cookie,其中包含您的 JWT。 JWT 本身也应该包含您的 CSRF 令牌。在 #4 中,您设置了一个 HTTP 标头(不是 cookie),其中还包含您的 CSRF 令牌。在您的 webapp 中,您只能读取包含 CSRF 令牌的 HTTP 标头。因此,当您收到服务器对您的身份验证请求的响应时,请读取包含 CSRF 令牌的 HTTP 标头并将其存储在浏览器的本地存储中。稍后,当您向服务器发出另一个请求时,从 localstorage 中读取 CSRF 令牌并将其设置为请求标头。
    猜你喜欢
    • 2012-11-25
    • 2021-10-01
    • 1970-01-01
    • 2020-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多