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

Ben*_*n M 114 authentication csrf stateless csrf-protection single-page-application

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

例:

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

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

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

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

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

  • 没有Http Session,也没有Cookies.

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

我错过了什么吗?

Ben*_*n M 152

我发现了一些关于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内容.


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

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

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

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

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


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

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

  • 关于CSRF的精彩总结!我会注意到,将您的令牌存储在localStorage或sessionStorage中容易受到XSS攻击,并且可以通过页面上的脚本查看数据 - 因此,如果您有从CDN提供的受损脚本或者其中一个存在恶意代码JS库,他们可以从这些存储位置窃取令牌.请参阅:https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/我认为最安全的方法是在cookie中存储JWT + CSRF令牌,然后将计算出的JWT与CSRF令牌放在请求头中. (34认同)

Sco*_*rth 54

TL; DR

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

阅读这篇文章的详细描述以获取更多信息 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标头匹配.

  • 值得指出的是(正如其他人在源链接的评论中所提到的),任何使用a)cookie的CSRF缓解(不是仅http或b)将CSRF令牌存储在本地存储中都容易受到XSS的攻击.这意味着所提出的方法可能有助于使用XSS保护JWT对攻击者的秘密,但是攻击者仍然能够在您的API上执行恶意请求,因为他能够提供有效的JWT(通过cookie,谢谢浏览器)和CSRF令牌(通过从本地存储/ cookie注入的JS读取). (3认同)
  • 是否应该在用户的api身份验证期间免除csrf令牌使用? (2认同)
  • 实际上,即使是 CSRF 令牌也无法在此级别的 XSS 上保护您,因为您假设攻击者可以访问 localStorage,目前访问它的唯一方法是具有脚本级别的访问权限,无论如何他们都可以查看 CSRF 令牌. (2认同)
  • 这不是@JohannesRudolph 所说的吗?一旦您将 CSRF 令牌存储在 Web 存储/非 http-only cookie 中,您就会增加 XSS 攻击的足迹,因为这些可以通过 JS 访问。 (2认同)
  • 不是这里的完全专家,但是如果您仍然像一开始那样接触 XSS,我不确定 * 最好添加... * 部分确实有效。对于攻击者来说,获取 CSRF 令牌可能稍微复杂一些(?),但最终他仍然能够代表您执行请求,即使实际上并不知道 JWT 令牌。那是对的吗?谢谢 (2认同)