题 使用无状态(=无会话)身份验证时,CSRF令牌是否必要?


当应用程序依赖无状态身份验证(使用HMAC之类的东西)时,是否有必要使用CSRF保护?

例:

  • 我们有一个单页应用程序(否则我们必须在每个链接上附加令牌: <a href="...?token=xyz">...</a>

  • 用户使用身份验证自己 POST /auth。成功验证后,服务器将返回一些令牌。

  • 令牌将通过JavaScript存储在单页面应用程序内的某个变量中。

  • 此令牌将用于访问受限制的URL,例如 /admin

  • 令牌将始终在HTTP标头内传输。

  • 没有Http Session,也没有Cookies。

据我了解,应该(?!)不可能使用跨站点攻击,因为浏览器不会存储令牌,因此它无法自动将其发送到服务器(这就是使用Cookies时会发生的情况/会议)。

我错过了什么吗?


96
2018-01-25 22:40


起源


关注Basic Auth。许多浏览器会自动为会话的其余部分发送基本身份验证标头。这可以使基本身份验证像cookie身份验证一样容易受到CSRF的攻击。 - phylae


答案:


我找到了一些关于CSRF +使用的信息 没有 用于身份验证的Cookie

  1. https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
    “既然你不依赖cookie,你就不需要防止跨站点请求”

  2. http://angular-tips.com/blog/2014/05/json-web-tokens-introduction/ 
    “如果我们沿着cookie方式走下去,你真的需要做CSRF以避免跨站点请求。这是我们在使用JWT时可以忘记的事情。”
    (JWT = Json Web Token,基于令牌的无状态应用程序身份验证)

  3. http://www.jamesward.com/2013/05/13/securing-single-page-apps-and-rest-services 
    “在不冒CSRF漏洞风险的情况下进行身份验证的最简单方法是简单地避免使用cookie来识别用户”

  4. http://sitr.us/2011/08/26/cookies-are-bad-for-you.html 
    “CSRF最大的问题是,cookie绝对无法抵御此类攻击。如果您使用cookie身份验证,您还必须采取其他措施来防范CSRF。您可以采取的最基本的预防措施是确保应用程序从不执行任何副作用以响应GET请求。“

如果您不使用cookie进行身份验证,还有更多页面表明您不需要任何CSRF保护。当然,你仍然可以将cookie用于其他一切,但是 避免 存储类似的东西 session_id 在里面。


如果您需要记住用户,有2个选项:

  1. localStorage:浏览器中的键值存储。即使在用户关闭浏览器窗口后,存储的数据也将可用。其他网站无法访问这些数据,因为每个网站都有自己的存储空间。

  2. sessionStorage:也是浏览器数据存储中的一个。不同之处在于:当用户关闭浏览器窗口时,数据将被删除。但是,如果您的webapp由多个页面组成,它仍然很有用。所以你可以做到以下几点:

    • 用户登录,然后将令牌存储在 sessionStorage
    • 用户单击链接,该链接将加载新页面(= a 真实 链接,没有javascript内容替换)
    • 您仍然可以从中访问令牌 sessionStorage
    • 要注销,您可以手动删除令牌 sessionStorage 或等待用户关闭浏览器窗口,这将清除所有存储的数据。

(两者都看看这里: http://www.w3schools.com/html/html5_webstorage.asp )


令牌身份验证是否有官方标准?

智威汤逊 (Json Web Token):我认为它仍然是一个草案,但它已被很多人使用,这个概念看起来简单而安全。 (IETF: http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-25 )
还有一些可用于框架的库。只是谷歌吧!


131
2017-08-08 07:49



关于CSRF的精彩总结!我会注意到,将您的令牌存储在localStorage或sessionStorage中容易受到XSS攻击,并且页面上的脚本可以查看数据 - 因此,如果您有从CDN提供的受损脚本或者其中一个存在恶意代码JS库,他们可以从这些存储位置窃取令牌。看到: stormpath.com/blog/... 我认为最安全的方法是在cookie中存储JWT + CSRF令牌,然后将计算出的JWT与CSRF令牌放在请求头中。 - Aaron Gray
关于:“您可以采取的最基本的预防措施是确保您的应用程序永远不会响应GET请求而执行任何副作用。” CSRF攻击是否可能伪造POST请求? - Costa
根据服务器端应用程序,它是可能的。有Web框架,使用类似的东西 http://.../someRestResource?method=POST。所以它基本上是一个 GET 请求,但服务器应用程序将其解释为 POST 请求,因为它被配置为使用 method 参数而不是HTTP标头。 ...关于常见的Web浏览器,它们强制执行Same-Origin-Policy并且只执行 GET 对外国服务器的请求。虽然它 可以 可以执行 POST 要求 如果 Web浏览器不应用这些Web标准(错误,恶意软件)。 - Benjamin M
除了 Server Side App:仍然无法发送请求正文,因为常见的浏览器不允许这样做。但是,如果服务器应用程序允许 method=POST,它也可能允许 body={someJson} 覆盖默认请求正文。这是非常糟糕的API设计,风险极高。虽然您的服务器应用程序允许 http://...?method=POST&body={someJson} 你应该真的想过你在那里所做的事情以及为什么以及如果有必要的话。 (我会说这是99,9999%的案例 不 必要)。此外,浏览器只能以这种方式发送几千字节。 - Benjamin M
@BenjaminM注意到Same Origin Policy仅阻止javaScript代码访问结果,因此当请求被“阻止”时它实际到达服务器 - jsbin.com/mewaxikuqo/edit?html,js,output 我只在firefox上测试过这个,但是你可以打开开发工具,看看即使你得到“Cross-Origin Request Blocked”,远程服务器也会看到整个请求。这就是为什么你必须有所有POST请求的令牌或自定义标题(如果可能的话) - Yoni Jah


TL; DR

如果在没有Cookie的情况下使用JWT,则无需使用CSRF令牌 - 但是!通过在会话/ localStorage中存储JWT,如果您的站点存在XSS漏洞(相当常见),则会暴露您的JWT和用户身份。最好添加一个 csrfToken JWT的关键,并将JWT存储在cookie中 secure 和 http-only 属性集。

阅读这篇文章,了解更多信息 https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage

您可以通过包含xsrfToken JWT声明来使此CSRF保护无状态:

{ "iss": "http://galaxies.com", "exp": 1300819380, "scopes": ["explorer", "solar-harvester", "seller"], "sub": "tom@andromeda.com", "xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e" }

因此,您需要将csrfToken存储在localStorage / sessionStorage以及JWT本身(存储在纯http和安全cookie中)中。然后,对于csrf保护,请验证JWT中的csrf标记是否与提交的csrf-token标头匹配。


42
2018-05-11 17:32



对我来说,这似乎是最常见的安全方法 - 特别是如果javascript应用程序被授予刷新令牌。你真的不是csrf的攻击者能够伪造到令牌刷新方法。 - J-DawG
是否应该在用户的api身份验证期间免除csrf令牌使用? - user805981
值得指出的是(正如其他人在源链接的评论中所提到的)任何使用a)cookie的CSRF缓解(不是仅http或b)将CSRF令牌存储在本地存储中都容易受到XSS的攻击。这意味着所提出的方法可能有助于使用XSS保护JWT免受攻击者的攻击,但是攻击者仍然可以在您的API上执行恶意请求,因为他能够提供有效的JWT(通过cookie,谢谢浏览器)和CSRF令牌(通过从本地存储/ cookie注入的JS读取)。 - Johannes Rudolph
实际上,即使是CSRF令牌也无法在此级别的XSS上保护您,因为您假设攻击者可以访问localStorage,当前访问的唯一方法是具有脚本级别访问权限,无论如何,他们可以查看CSRF令牌。 - itsnotvalid
这不是@JohannesRudolph所说的吗?只要将CSRF令牌存储在Web存储/非http-only cookie中,就会增加XSS攻击的范围,因为这些攻击可以通过JS访问。 - adam-beck