当应用程序依赖无状态身份验证(使用类似HMAC之类的东西)时,是否有必要使用CSRF保护?
示例:
我们有一个单页应用(否则我们必须在每个链接上添加令牌:<a href="...?token=xyz">...</a>
。
用户使用POST /auth
对自己进行身份验证。验证成功后,服务器将返回一些令牌。
令牌将通过JavaScript存储在单页应用内的某个变量中。
此令牌将用于访问/admin
等受限制的网址。
令牌将始终在HTTP标头内传输。
没有Http Session,也没有Cookies。
据我了解,应该(?!)不可能使用跨站点攻击,因为浏览器不会存储令牌,因此它无法自动将其发送到服务器(这就是当发生时会发生的情况)使用Cookies / Session)。
我错过了什么吗?
答案 0 :(得分:143)
我使用没有 Cookie进行身份验证时发现了一些有关CSRF +的信息:
https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
“既然你不依赖cookie,你就不需要防止跨网站请求”
http://angular-tips.com/blog/2014/05/json-web-tokens-introduction/
“如果我们沿着cookie方式走下去,你真的需要做CSRF以避免跨站点请求。这是我们在使用JWT时可以忘记的事情。”
(JWT = Json Web Token,基于令牌的无状态应用程序身份验证)
http://www.jamesward.com/2013/05/13/securing-single-page-apps-and-rest-services
“在不冒CSRF漏洞风险的情况下进行身份验证的最简单方法是简单地避免使用cookie来识别用户”
http://sitr.us/2011/08/26/cookies-are-bad-for-you.html
“CSRF最大的问题是,cookie绝对无法抵御此类攻击。如果您使用cookie身份验证,您还必须采取其他措施来防范CSRF。您可以采取的最基本的预防措施是确保应用程序从不执行任何副作用以响应GET请求。“
如果您不使用cookie进行身份验证,还有更多页面表明您不需要任何CSRF保护。当然,您仍然可以将Cookie用于其他所有内容,但避免在其中存储session_id
之类的内容。
如果您需要记住用户,有两个选项:
localStorage
:浏览器中的键值存储。即使在用户关闭浏览器窗口后,存储的数据也将可用。其他网站无法访问这些数据,因为每个网站都有自己的存储空间。
sessionStorage
:也是浏览器数据存储中的一个。不同之处在于:当用户关闭浏览器窗口时,数据将被删除。但是,如果您的webapp由多个页面组成,它仍然很有用。所以你可以做到以下几点:
sessionStorage
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)
还有一些可用于框架的库。只是谷歌吧!
答案 1 :(得分:49)
TL; DR
如果在没有Cookie的情况下使用JWT,则无需使用CSRF令牌 - 但是!通过将JWT存储在session / localStorage中,如果您的站点存在XSS漏洞(相当常见),则会公开您的JWT和用户身份。最好向JWT添加csrfToken
密钥,并将JWT存储在设置了secure
和http-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标头匹配。