当应用程序依赖无状态身份验证(使用HMAC之类的东西)时,是否有必要使用CSRF保护?
例:
-
我们有一个单页应用程序(否则我们必须在每个链接上附加令牌:
<a href="...?token=xyz">...</a>
. -
用户使用
POST /auth
验证自己 . 成功验证后,服务器将返回一些令牌 . -
令牌将通过JavaScript存储在单页面应用程序内的某个变量中 .
-
此令牌将用于访问受限制的URL,如
/admin
. -
令牌将始终在HTTP标头内传输 .
-
没有Http Session,也没有Cookies .
据我了解,应该(?!)不可能使用跨站点攻击,因为浏览器不会存储令牌,因此它无法自动将其发送到服务器(这就是使用Cookies时会发生的情况/ Session ) .
我错过了什么吗?
2 回答
TL; DR
如果在没有Cookie的情况下使用JWT,则无需使用CSRF令牌 - 但是!通过在会话/ localStorage中存储JWT,如果您的站点存在XSS漏洞(相当常见),则会暴露您的JWT和用户身份 . 最好将一个
csrfToken
键添加到JWT并将JWT存储在一个设置了secure
和http-only
属性的cookie中 .阅读这篇文章的详细描述了解更多信息https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage
因此,您需要将csrfToken存储在localStorage / sessionStorage以及JWT本身(存储在纯http和安全cookie中)中 . 然后,对于csrf保护,请验证JWT中的csrf标记是否与提交的csrf-token标头匹配 .
我发现了一些有关CSRF的信息,使用 no cookie进行身份验证:
https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
"since you are not relying on cookies, you don't need to protect against cross site requests"
http://angular-tips.com/blog/2014/05/json-web-tokens-introduction/
"If we go down the cookies way, you really need to do CSRF to avoid cross site requests. That is something we can forget when using JWT as you will see."
(JWT = Json Web Token,基于令牌的无状态应用程序身份验证)
http://www.jamesward.com/2013/05/13/securing-single-page-apps-and-rest-services
"The easiest way to do authentication without risking CSRF vulnerabilities is to simply avoid using cookies to identify the user"
http://sitr.us/2011/08/26/cookies-are-bad-for-you.html
"The biggest problem with CSRF is that cookies provide absolutely no defense against this type of attack. If you are using cookie authentication you must also employ additional measures to protect against CSRF. The most basic precaution that you can take is to make sure that your application never performs any side-effects in response to GET requests."
还有更多页面,表明您没有使用cookie进行身份验证 . 当然你仍然可以在其他所有内容中使用cookie,但 avoid 在其中存储了类似
session_id
的内容 .如果您需要记住用户,有2个选项:
localStorage
:浏览器中的键值存储 . 即使在用户关闭浏览器窗口后,存储的数据也将可用 . 其他网站无法访问这些数据,因为每个网站都有自己的存储空间 .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)
还有一些可用于框架的库 . 只是谷歌吧!