使用无状态(=无会话)身份验证时需要CSRF令牌吗?


125

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

例:

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

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

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

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

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

  • 没有Http会话,也没有Cookie。

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

我想念什么吗?


6
请注意基本身份验证。许多浏览器会自动发送剩余会话的基本身份验证标头。这会使基本身份验证像Cookie身份一样容易受到CSRF的攻击。
phylae

Answers:


159

我发现使用约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令牌,这是针对无状态应用程序的基于令牌的身份验证)

  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:也是浏览器中的数据存储区。区别在于:当用户关闭浏览器窗口时,数据将被删除。但是,如果您的Web应用包含多个页面,它仍然很有用。因此,您可以执行以下操作:

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

(两者都可以在这里查看:http : //www.w3schools.com/html/html5_webstorage.asp


令牌认证有任何官方标准吗?

JWT(Json Web令牌):我认为它仍然是草案,但是它已经为许多人所使用,并且该概念看上去简单而安全。(IETF:http//tools.ietf.org/html/draft-ietf-oauth-json-web-token-25
也有很多框架可用的库。只是谷歌!


37
关于CSRF的精彩摘要!我会注意到,将令牌存储在localStorage或sessionStorage中容易受到XSS攻击,并且页面上的脚本可以查看数据-因此,如果您的CDN提供了受感染的脚本,或者其中一个包含恶意代码, JS库,它们可以从这些存储位置中窃取令牌。请参阅:stormpath.com/blog/…我认为最安全的方法是将JWT + CSRF令牌存储在cookie中,然后将带有CSRF令牌的计算出的JWT放在请求标头中。
亚伦·格雷

关于:“您可以采取的最基本的预防措施是确保您的应用程序永远不会响应GET请求而产生任何副作用。” CSRF攻击是否可能伪造POST请求?
2013年

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

1
补充Server Side App::仍然无法发送请求正文,因为常见的浏览器不允许这样做。但是,如果Server App允许method=POST,则它可能还允许body={someJson}覆盖默认请求正文。那真的是很糟糕的API设计,而且风险极大。尽管如果您的Server App允许,http://...?method=POST&body={someJson}您应该真正考虑一下您在那里所做的事情,原因以及是否必要。(在99,9999%的情况下,这是没有必要的)。另外,浏览器只能以这种方式发送几千字节。
本杰明·M

@BenjaminM注意,相同起源策略仅阻止javaScript代码访问结果,因此,在请求被“阻止”时,它实际上到达了服务器-jsbin.com/mewaxikuqo/edit?html,js,output我仅在firefox上对此进行了测试,但是您可以打开开发工具,甚至可以看到即使“跨域请求被阻止”,远程服务器也可以看到整个请求。这就是为什么您必须对所有POST请求都拥有令牌或自定义标头(如果可能的话,还必须包含两者)
Yoni Jah

59

TL; DR

如果使用JWT,但不使用Cookie,则无需CSRF令牌-但是!通过将JWT存储在session / localStorage中,如果您的站点具有XSS漏洞(相当普遍),则可以公开JWT和用户的身份。最好向csrfTokenJWT 添加密钥,并将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标头匹配。


2
用户的api身份验证期间是否应豁免csrf令牌使用?
user805981

3
值得指出的是(如其他人在源链接的评论中也提到的那样),任何使用a)cookie(非仅http或b)将CSRF令牌存储在本地存储中的CSRF缓解措施都容易受到XSS的攻击。这意味着,所提出的方法可能有助于使使用XSS的JWT免受攻击者的注意,但是攻击者仍然能够在您的API上执行恶意请求,因为他能够提供有效的JWT(通过cookie,谢谢浏览器)和CSRF令牌(通过从本地存储/ cookie注入的JS读取)。
约翰内斯·鲁道夫

1
实际上,即使CSRF令牌也无法在此级别的XSS上保护您,因为您假设攻击者可以访问localStorage,而当前访问的唯一方法就是具有脚本级访问权限,无论如何他们都可以查看CSRF令牌。
itsnotvalid

1
那不是@JohannesRudolph在说什么吗?一旦将CSRF令牌存储在Web Storage /非仅HTTP cookie中,您就增加了XSS攻击的范围,因为可以通过JS访问这些令牌。
亚当·贝克

1
这里不是一个全面的专家,但是如果您仍然像刚开始时一样接触XSS,我不确定这部分是否值得添加...确实成立。对于攻击者来说,拥有CSRF令牌可能稍微复杂一些(?),但最终,即使实际上不知道JWT令牌,他仍然能够代表您执行请求。那是对的吗?谢谢
superjos
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.