在浏览器中存储JWT的位置?如何防范CSRF?

时间:2014-11-21 17:44:17

标签: security authentication cookies csrf jwt

我知道基于cookie的身份验证。可以应用SSL和HttpOnly标志来保护来自MITM和XSS的基于cookie的身份验证。但是,需要采取更多特殊措施以保护其免受CSRF的影响。它们有点复杂。 (reference

最近,我发现JSON Web Token(JWT)作为身份验证解决方案非常热门。我知道有关编码,解码和验证JWT的内容。但是,我不明白为什么有些网站/教程在使用JWT时不需要CSRF保护。我已经阅读了很多,并试图总结下面的问题。我只是希望有人可以提供JWT的全貌并澄清我对JWT误解的概念。

  1. 如果JWT存储在cookie中,我认为它与基于cookie的身份验证相同,只是服务器不需要有会话来验证cookie /令牌。如果没有实施特殊措施,CSRF仍存在风险。 JWT不是存储在cookie中吗?

  2. 如果JWT存储在localStorage / sessionStorage中,那么没有cookie所以不需要防止CRSF。问题是如何将JWT发送到服务器。我发现here建议使用jQuery通过ajax请求的HTTP头发送JWT。那么,只有ajax请求才能进行身份验证吗?

  3. 此外,我发现还有一个blog节目使用“授权标题”和“承载”来发送JWT。我不明白博客谈论的方法。有人可以解释一下“授权标题”和“持票人”的更多信息吗?这是否使所有请求的HTTP头传输JWT?如果是,CSRF怎么样?

6 个答案:

答案 0 :(得分:109)

我们需要在客户端计算机上存储JWT。如果我们将它存储在LocalStorage / SessionStorage中,那么它很容易被XSS攻击抓取。如果我们将其存储在cookie中,那么黑客可以在CSRF攻击中使用它(不读取它)并冒充用户并联系我们的API并发送请求以执行操作或代表用户获取信息。

但有几种方法可以确保JWT在cookie中不被轻易窃取(但仍有一些先进技术可以窃取它们)。但是,如果您想依赖LocalStorage / SessionStorage,那么可以通过简单的XSS攻击来访问它。

因此,为了解决CSRF问题,我在我的应用程序中使用Double Submit Cookies。

双提交Cookie方法

  1. 将JWT存储在HttpOnly cookie中,并以安全模式使用它通过HTTPS传输。

  2. 大多数CSRF攻击在其请求中与原始主机具有不同的来源或引荐来源标头。因此,检查标题中是否有任何标题,是否来自您的域名!如果不拒绝他们。如果请求中没有origin和referrer,那么不用担心。您可以依赖X-XSRF-TOKEN标头验证结果,我将在下一步中解释。

  3. 虽然浏览器会自动为请求域提供Cookie,但有一个有用的限制:网站上运行的JavaScript代码无法读取其他网站的Cookie。我们可以利用它来创建我们的CSRF解决方案。为了防止CSRF攻击,我们必须创建一个额外的Javascript可读cookie,称为:XSRF-TOKEN。必须在用户登录时创建此cookie,并且该cookie应包含随机的,不可猜测的字符串。我们还将这个号码保存在JWT本身作为私人索赔。每次JavaScript应用程序想要发出请求时,都需要读取此令牌并将其发送到自定义HTTP标头中。因为这些操作(读取cookie,设置标题)只能在JavaScript应用程序的同一个域上完成,所以我们可以知道这是由使用我们的JavaScript应用程序的真实用户完成的。

  4. Angular JS让您的生活轻松

    幸运的是,我在我们的平台中使用Angular JS,而Angular包装了CSRF令牌方法,使我们更容易实现。对于我们的Angular应用程序对服务器的每个请求,Angular $http服务将自动执行以下操作:

    • 在当前域中查找名为XSRF-TOKEN的cookie。
    • 如果找到该cookie,它会读取该值并将其作为X-XSRF-TOKEN标头添加到请求中。

    因此,客户端实现将自动为您处理!我们只需要在服务器端的当前域上设置一个名为XSRF-TOKEN的cookie,当我们的API从客户端接到任何调用时,它必须检查X-XSRF-TOKEN标头并将其与{{1}进行比较在JWT中。如果它们匹配,则用户是真实的。否则,它是伪造的请求,您可以忽略它。这种方法的灵感来自于" Double Submit Cookie"方法。

    注意

    实际上,您仍然容易受到XSS的攻击,只是攻击者无法窃取您的JWT令牌供以后使用,但他仍然可以向您的用户发出请求。代表使用XSS。

    无论是将JWT存储在XSRF-TOKEN中还是将XSRF令牌存储在非HttpOnly cookie中,都可以通过XSS轻松获取。甚至你的HttpOnly cookie中的JWT也可以通过像XST method这样的高级XSS攻击来抓取。

    因此,除了Double Submit Cookies方法之外,您必须始终遵循针对XSS的最佳实践,包括转义内容。这意味着删除任何可能导致浏览器执行您不​​希望的操作的可执行代码。通常,这意味着删除导致JavaScript被评估的localStorage标记和HTML属性。

    在这里阅读更多内容:

答案 1 :(得分:50)

JWT令牌很受欢迎,因为它们在OAuth 2.0OpenID Connect等新授​​权和身份验证协议中用作默认令牌格式。

当令牌存储在cookie中时,浏览器会自动将它与每个请求一起发送到同一个域,这仍然容易受到CSRF攻击。

承载身份验证是HTTP中定义的authentication schemes之一。它基本上意味着YOU将(JWT)令牌粘贴在请求的Authorization HTTP标头中。浏览器会NOT自动为您执行此操作,因此不适合保护您的网站。由于浏览器不会自动将标头添加到您的请求中,因此它不容易受到CSRF攻击,这取决于您的身份验证信息会自动提交到原始域。

承载方案通常用于保护通过AJAX调用或移动客户端使用的Web API(REST服务)。

答案 2 :(得分:15)

现在,在2020年,只需将JWT令牌存储在带有SameSite=strict的cookie中即可击败CSRF。当然,也要保留securehttpOnly

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite

答案 3 :(得分:5)

存储JWT的整个问题的另一个角度:

  1. JWT永远不应存储在您的localStorage中
  2. 实际上,它们甚至都不应该存储在您的Cookie中除非您能够实施非常严格的CSRF保护

Checkout this for motivation

  • JWT作为id_token就像您的用户凭据
  • JWT作为access_token就像您的会话令牌

最安全的选项是内存中Checkout this for a deep dive

答案 4 :(得分:2)

在网络浏览器中,您可以将 JWT 存储在本地/会话存储cookie中。两者都有漏洞。你可以选择你喜欢的一个,但你应该把安全作为一个整体来保护,流程应该设计得很好。如果你只防止 XSRF 和 XSS,它不会帮助你。这是对您问题的简短回答。

首先要防止用户数据被盗。非常有问题的是 XSS 攻击。如果您使用存储,攻击者可以窃取令牌 - 将令牌发送到他的服务器并发出窃取用户数据的请求。如果你使用 httpOnly cookie,他不能窃取令牌,但他可以发送请求(浏览器包含 cookie,如果脚本在同一个域中),读取响应并将用户数据发送到他的服务器。结果是一样的。

为了防止将数据发送到不同域的服务器,您可以使用 Content-Security-Policy 标头。我建议研究所有安全标头和网络安全。好的资源是 OWASP。这个论坛不是写很多页面。

XSRF (CSRF)

如果您使用 cookie,那么应用程序很容易受到这种攻击。

如何预防:

设置 httpOnly、secured 和 SameSite=strict 标志。您还可以使用不带 httpOnly 的第二个 cookie XSRF-TOKEN 并将其值与此 cookie 一起发送到标头 X-Xsrf-Token 中。但是如果浏览器支持,这可以通过 SameSite 标志解决。

XSS

从某种意义上说,存储和 cookie 都容易受到 XSS 的攻击。使用 javascript 代码,您可以读取存储,并且可以使用浏览器包含的 cookie 向服务器发送请求,因为您在同一域中。如果您使用用户输入,您应该对它们进行转义/消毒。您还可以使用标题 x-xss-protection。最有问题的是第 3 方 js 库中的恶意代码,因为您无法逃脱它并且它在同一域上运行。您可以防止用户数据因您的错误而被盗,但此类代码可能会给您的应用程序和用户带来不同的问题。

答案 5 :(得分:1)

将访问令牌存储在内存中,并将刷新令牌存储在cookie中

为什么对CSRF如此安全?

尽管提交给/refresh_token的表单将起作用,并且将返回新的访问令牌,但是如果攻击者使用的是HTML表单,则攻击者将无法读取响应。为了防止攻击者成功发出获取或AJAX请求并读取响应,这要求正确设置Authorization Server的CORS策略,以防止未经授权的网站发出请求。

您可以在此处了解更多信息:

https://dev.to/cotter/localstorage-vs-cookies-all-you-need-to-know-about-storing-jwt-tokens-securely-in-the-front-end-15id