89

当应用程序依赖无状态身份验证(使用类似HMAC)时,是否有必要使用CSRF保护?使用无状态(= Sessionless)身份验证时需要CSRF令牌吗?

例子:

  • 我们已经有了一个单页的应用程序(否则我们不得不追加每条链路上的标记:。<a href="...?token=xyz">...</a>

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

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

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

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

  • 没有Http Session,也没有Cookies。

据我了解,应该有(?!)是没有可能利用跨站攻击,因为浏览器不会存储令牌,因此它不能自动将其发送到服务器(这是使用Cookies/Session时会发生什么)。

我错过了什么吗?

+5

请注意基本身份验证。许多浏览器会自动发送会话剩余部分的基本身份验证标头。这可以使基本身份验证容易受到CSRF作为cookie身份验证的影响。 – phylae

回答

121

我发现了大约CSRF +使用没有 cookie进行认证的一些信息:

  1. https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
    “因为你不是靠饼干,你并不需要,以防止跨站点请求”

  2. http://angular-tips.com/blog/2014/05/json-web-tokens-introduction/
    “如果我们走下来的饼干方式,你真正需要做的CSRF避免交叉站点的请求,这是我们不能忘记当你使用智威汤逊时你会看到。“
    (JWT = JSON网络令牌,无国籍应用基于令牌的认证)

  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最大的问题在于,cookies绝对无法防御此类攻击,如果您使用cookie身份验证,还必须采取额外措施来防止CSRF,最基本的precaut您可以采取的措施是确保您的应用程序不会响应GET请求执行任何副作用。“

如果您不使用cookie进行身份验证,则有更多页面指出您不需要任何CSRF保护。当然,你仍然可以使用cookies来处理其他事情,但是避免在里面存储任何类似session_id的东西。


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

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

  2. sessionStorage:另外一个在浏览器中的数据存储。区别在于:当用户关闭浏览器窗口时,数据被删除。但如果你的web应用程序由多个页面组成,它仍然很有用。所以,你可以做到以下几点:

    • 用户登录,那么你存储在sessionStorage
    • 用户令牌点击一个链接,它加载了新的一页(=一个真正链接,没有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
也有很多可用的框架库。只需谷歌!

+18

关于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令牌一起放入请求头中。 –

+0

关于:“您可以采取的最基本的预防措施是确保您的应用程序不会响应GET请求执行任何副作用。” CSRF攻击可能伪造POST请求吗? – Costa

+0

根据服务器端应用程序,它是可能的。有Web框架,它使用类似'http://.../someRestResource?method = POST'。所以它基本上是一个GET请求,但服务器应用程序将它解释为POST请求,因为它被配置为使用'method'参数而不是HTTP头。 '...'关于常见的Web浏览器,他们强制使用同源策略,并且只对外部服务器执行GET请求。虽然如果**网页浏览器不适用这些网络标准(错误,恶意软件),它可能*可能执行'POST'请求​​*。 –

33

JWT,如果使用没有Cookie,否定CSRF令牌的需要 - 但!通过将JWT存储在session/localStorage中,如果您的站点存在XSS漏洞(相当常见),则会暴露JWT和用户的身份。最好向JWT添加一个csrfToken密钥,并将JWT存储在一个包含securehttp-only属性的cookie中。

阅读这篇文章,有一个很好的说明更多的信息 https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage

可以使这个CSRF保护无国籍由包括xsrfToken JWT要求:

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

所以你会需要将csrfToken存储在localStorage/sessionStorage以及JWT本身(存储在http-only和安全cookie中)。然后为了保护csrf,请验证JWT中的csrf标记是否与提交的csrf-token标头匹配。

+0

这似乎是我最常识的安全方法 - 尤其是如果JavaScript应用程序被授予刷新令牌。你真的不是csrf的攻击者能够伪造成令牌刷新方法。 –

+2

应该在用户的api验证过程中豁免csrf令牌的使用情况吗? – user805981

+1

值得指出的是(正如其他人在源代码链接的评论中也提到的那样)任何使用a)不是http-only的cookie或者b)将CSRF令牌存储在本地存储中的CSRF缓解容易受到XSS的影响。这意味着所提出的方法可能有助于保持JWT对使用XSS的攻击者的秘密,但是攻击者仍然能够在您的API上执行恶意请求,因为他能够提供有效的JWT(通过cookie,感谢您的浏览器)和CSRF令牌(通过从本地存储/ cookie中注入的JS读取)。 –

相关问题