Cookies是否可以保护令牌免受XSS攻击? [英] Do cookies protect tokens against XSS attacks?

查看:137
本文介绍了Cookies是否可以保护令牌免受XSS攻击?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为基于浏览器的Javascript Web应用程序构建基于JWT的(JSON Web令牌)身份验证机制,并与无状态服务器(无用户会话!)一起使用,我想一劳永逸地知道,如果使用将我的JWT令牌存储在 cookie 中可以保护我的令牌免受XSS攻击,或者没有保护措施,那么与在Javascript应用程序中使用浏览器本地存储相比,没有真正的优势.

I'm building a JWT-based (JSON Web Token) authentication mechanism for an browser-based Javascript web app, working with a stateless server (no user-sessions!) and I want to know, once and for all, if using storing my JWT token in a cookie will protect my token from XSS attacks, or if there is no protection, so there's no real advantage over using browser local storage in my Javascript app.

我已经在SO和许多博客中看到并回答了这个问题,但是我从未见过真正令我满意的答案.

I have seen this question asked and answered in SO and in many blogs, but I've never seen an answer that really satisfies me.

这个问题最初是在征求意见的基础上提出的,并给出了我的原始措词,这是正确的.因此,让我在这里和现在都清楚地说,我不希望基于模糊的开发人员惰性等观点发表意见-这就是要消除的基本规则.我想要的是有证据支持的是/否答案.要么

This question was originally held on the basis that it solicits opinion - and given my original wording, rightly so. So let me make it clear here and now that I don't want an opinion based on vague notions of developer laziness or such - that's what the ground rules are meant to eliminate. What I want is an evidence-backed Yes/No answer. Either:

  • 是的,可以保护cookie免受XSS和CSRF的侵害,这就是这种方式"
  • 不,通过保护cookie免受CSRF的侵扰,您始终可以将它们置于最初使cookie成为一个好主意的XSS攻击中".
  • "Yes, cookies can be protected from XSS and CSRF and here's how" or
  • "No, by protecting your cookies from CSRF, you always open them up to the same kind of XSS attack that made cookies a good idea in the first place"

因此,我将重申一些简单的基本规则,并事先指出漏洞,以便您(专家)可以直通我.

So I'm going to restate the question, with some simplifying ground-rules, and point out the holes in advance, so that you, the experts, can set me straight.

  • 您的应用程序是javascript浏览器应用程序-可能在AngularJS中,但可能是定制的.它通过REST调用与服务器通信.假设是jQuery $ ajax调用.

  • Your app is a javascript browser app - it might be in AngularJS, but it might be custom-built. It communicates with the server via REST calls. Let's say, jQuery $ajax calls.

服务器是无状态的:没有会话管理.

The server is stateless: there is no session management.

应用程序用户将JWT作为主要身份验证令牌(在OAuth2中为访问令牌"),并使用秘密签名密钥在服务器上对其进行验证

The app users JWTs as the main authentication token ('access token' in OAuth2 parlance) and validates them on the server using a secret signing key

忽略cookie的其他重要优点:浏览器管理,更少的机会进行不好的编码等.为此,我想考虑绝对的安全性,并假设我们可以胜任地对这两种机制进行编码.

Ignore other important advantages of cookies: browser management, less chance of coding poorly, etc. For this battle, I want to consider the absolute security, and assume we can competently code either mechanism.

忽略cookie的其他缺点,例如非浏览器应用程序等.在这场战斗中,我们只关注基于浏览器的javascript应用程序.

Ignore other disadvantages of cookies, such as non-browser apps, etc. For this battle we are only concerned with a browser-based javascript app.

以非cookie方式使用标头或请求正文来传输令牌都无关紧要;如果您使用的是本地存储还是会话存储,也没有关系-忽略那里的任何安全性差异.是的,我知道从技术上讲Cookies会使用标头,请忽略该标头.

It doesn't matter whether you use a header or a request body to transmit tokens in the non-cookie approach; nor does it matter if you're using local storage vs session storage - ignore any security differences there. And yes I know that technically Cookies use headers, ignore that.

简而言之,我们只想比较浏览器句柄令牌与您的JavaScript句柄令牌以及比较的XSS和CSRF安全风险.

在红色角落中,

In the red corner, Auth0: Local Storage beats Cookies, because XSS is easier to fix than CSRF

在蓝色角落中, Stormpath :Cookies比标题更重要,因为实际上CSRF比XSS更容易修复.

In the blue corner, Stormpath: Cookies beats headers, because actually CSRF is easier to fix than XSS.

(下面两个参数的摘要均在其中)

(excerpts of both arguments in detail below)

XSS和CSRF(我们将交替使用CSRF和XSRF:C似乎在文档中更流行,X在代码中更受欢迎)

XSS and CSRF (we'll use CSRF and XSRF interchangeably: the C seems to be more popular in documentation, the X in code)

这是我对攻击类型的超级简化总结:

Here's my super-simplified summary of the attack types:

让我们假设您的无状态,经过JWT身份验证的javascript浏览器应用程序是用于在线银行业务的,攻击者"Evil Corp"想要提交一个AJAX REST调用,该调用可通过模拟用户将资金转移到他们的帐户中.

Let's assume your stateless, JWT-authenticated, javascript browser app is for online banking and the attacker, "Evil Corp", wants to submit an AJAX REST call that transfers funds to their account by impersonating your users.

XSS (跨站点脚本)

(正如Stormpath指出的那样,攻击媒介很多-我将选一个)

(As Stormpath points out, there are many attack vectors - I'll pick one)

Evil Corp购买了用于输入密码的漂亮文本字段小部件的github帐户权限.他们知道您的银行网站正在使用它,因此当您输入密码并按Enter键时,他们会更新它以提交AJAX请求以将资金转入他们的帐户.您的构建系统会愚蠢地提取更新并投入生产.

Evil Corp buys the github account rights for the nifty text field widget you use for password entry. They know your bank site uses it, so they update it to submit AJAX requests to transfer funds to their account when you type in your passord and hit enter. Your build system foolishly pulls the update and puts in production.

CSRF (跨站点请求伪造)

Evil Corp知道您的银行站点使用Cookie中的JWT来验证交易,因此他们编写了一个Web应用程序,该应用程序提交AJAX请求以将资金转入其帐户.他们将其托管在自己的evil.com网站上,当您碰巧登录到另一个标签中的银行网站时,会通过电子邮件(网络钓鱼)或其他方式将您引诱到那里.浏览器提交来自evil.com的请求,但由于它会转到正确的站点:银行,因此附加了您的JWT.

Evil Corp knows your bank site uses JWTs in cookies to authenticate transactions, so they write a web app that submits AJAX requests to transfer funds to their account. They host this on their own evil.com site, and lure you there with an email (phishing) or some other way, when you happen to be logged into your bank site in another tab. The browser submits the request from evil.com, but attaches your JWT becaues it's going to the correct site: the bank.

针对XSS的防御措施是对网站中的代码非常小心,以免浏览器在未对其进行消毒(删除javascript和html)以及所有第三方库(Evil的文本)的情况下,不允许浏览器处理用户键入的内容.字段小部件)将在使用前进行审核.正如Stormpath正确指出的那样,这很困难,几乎是不可能的.

The defence against XSS is to be very careful about the code in your site so that you never let the browser process something the user types in without sanitizing it (removing javascript and html) and that all the 3rd party libraries (Evil's text field widget) are vetted before being used. As Stormpath rightly points out, this is hard, bordering on impossible.

针对CSRF的防御措施是使用双提交cookie的形式.这意味着我们的服务器创建一个令牌(安全地随机字符串),并以可读的cookie(按照惯例将其称为"XSRF-TOKEN")将其发送到我们的Javascript浏览器应用程序,并且我们的Javascript会在每次请求时以标头或正文形式将其发送回

The defence against CSRF is to use a form of double-submit-cookie. This means our server creates a token (securely random string) and sends it to our Javascript browser app in a readable cookie (call it "XSRF-TOKEN" by convention), and our Javascript sends it back in a header or body with every request.

实际上,双和cookie只是一种防御方式,它需要使用有状态的服务器会话,而其他任何一种(我想不到!)都无法提供更好的保护.通过将令牌放入JWT并将其在服务器端与标头或正文中的令牌进行比较,可以实现无状态.

Actually, double-sumbit-cookie's are only one defence agasint CSRF, but some others require stateful server sessions and no other (I think!) offers any better protection. The statelessness can be achieved by also putting the token in the JWT and comparing it on the server side with the one that comes in the header or body.

但是,这种防御的真正CSRF破坏质量是同源策略,意味着只有我们的应用从我们的域加载的javascript才能读取该cookie.因此,即使evilcorp.com上的javascript可以随其请求发送我们的cookie,也不能嵌入我们的XSRF-TOKEN,因为它在第一时间无法读取地方.

But the real CSRF-busting quality of this defence, is that same-origin-policy mean that only the javascript that our app loaded from our domain can read that cookie. So even if the javascript on evilcorp.com can send our cookies with its requests, it can't embed our XSRF-TOKEN because it can't read it in the first place.

真正简化CSRF:

  • CSRF 攻击起作用,因为附加Cookie的浏览器仅取决于请求的目标.
  • CSRF 防御之所以有效,是因为Javascript对cookie的访问取决于Javascript的 origin .
  • CSRF attacks work because a browser attaching a cookie depends only on the destination of a request.
  • CSRF defences work because Javascript access to a cookie depends on the origin of the Javascript.

使用XSS比使用XSRF Coo​​kies更容易,因为Cookie具有此功能, 允许从服务器端设置一个HttpOnly标志,因此它们只能是 在服务器上访问,而不是从JavaScript访问.这很有用,因为 它保护该cookie的内容可以通过注入来访问 客户端代码(XSS).由于令牌存储在本地/会话中 存储或客户端Cookie,它们容易受到XSS攻击 使攻击者可以访问令牌.这是一个有效的关注点,并且 因此,您应该将令牌的有效期保持在较低水平.

It's easier to deal with XSS than XSRF Cookies have this feature that allows setting an HttpOnly flag from server side so they can only be accessed on the server and not from JavaScript. This is useful because it protects the content of that cookie to be accessed by injected client-side code (XSS). Since tokens are stored in local/session storage or a client side cookie, they are open to an XSS attack getting the attacker access to the token. This is a valid concern, and for that reason you should keep your tokens expiration low.

但是,如果你 考虑一下cookie的攻击面,主要之一是 XSRF.现实情况是XSRF是最容易被误解的一种 攻击和一般的开发人员甚至可能不了解 风险,因此许多应用程序缺乏抗XSRF机制.然而, 每个人都知道什么是注射.简而言之,如果允许的话 在您的网站上输入内容,然后在不进行转义的情况下进行渲染,您 向XSS开放.因此,根据我们的经验,更容易保护 抵御XSS胜过抵御XSRF.除此之外,抗XSRF是 并非内置在每个Web框架上.另一方面,XSS很容易 通过使用大多数情况下默认情况下可用的转义语法来防止 模板引擎. https ://auth0.com/blog/2014/01/27/ten-things-you-should-know-about-tokens-and-cookies#xss-xsrf

But if you think about the attack surface on cookies, one of the main ones is XSRF. The reality is that XSRF is one of the most misunderstood attacks, and the average developer, might not even understand the risk, so lots of applications lack anti-XSRF mechanism. However, everybody understands what injection is. Put simply, if you allow input on your website and then render that without escaping it, you are open to XSS. So based on our experience, it is easier to protect against XSS than protecting against XSRF. Adding to that, anti-XSRF is not built-in on every web framework. XSS on the other hand is easy to prevent by using the escape syntax available by default on most template engines. https://auth0.com/blog/2014/01/27/ten-things-you-should-know-about-tokens-and-cookies#xss-xsrf

Stormpath的论点

Stormpath建议您将JWT存储在Web的cookie中 应用程序,因为它们提供了额外的安全性,并且 使用现代Web框架保护CSRF的简便性. HTML5 Web存储易受XSS攻击,具有较大的攻击面 区域,并可能在成功攻击时影响所有应用程序用户. https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/

Stormpath recommends that you store your JWT in cookies for web applications, because of the additional security they provide, and the simplicity of protecting against CSRF with modern web frameworks. HTML5 Web Storage is vulnerable to XSS, has a larger attack surface area, and can impact all application users on a successful attack. https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/

也:

我看到了很多讨论,其中将cookie限制在访问之外 令牌.虽然我们都被存储了会话ID的系统所累 Cookie中,并且该cookie不安全,因此被盗.那 很烂,但这不是使用令牌的原因.这是避免的原因 非安全,非https的cookie. https://stormpath.com/blog/token-auth-spa/

I see a lot of discussions where cookies are pitted against access tokens. While we’ve all been burned by systems that store a session ID in a cookie, and that cookie is not secured and thus gets stolen. That sucks, but its not a reason to use tokens. Its a reason to avoid non-secure, non-https cookies. https://stormpath.com/blog/token-auth-spa/

我的收获

Stormpath支持cookie的论点令人信服,但是有一个漏洞,我看不出它们能解决的很清楚:

My take

Stormpath's argument in favour of cookies is pretty convincing, but there's a hole in it that I don't see them addressing clearly:

两次提交CSRF防御依赖于以下事实:我的CSRF攻击者无法访问我的cookie:其中包含XSRF-TOKEN的cookie.但是,该cookie难道不像本地存储一样容易受到XSS攻击吗?

XSS漏洞可以在 my 域上运行javascript,因此可以读取与javascript相同的cookie. (浏览器不知道这不是我的Javascript)

An XSS exploit can run javascript on my domain, so it can read the same cookies my javascript can. (The browser doesn't know that it isn't my Javascript)

从另一面看:本地存储受相同来源策略保护的程度与可读cookie一样多.如果我使用的是Auth0方法,那么XSS攻击者就会知道如何在本地存储中找到我的JWT并使用它.相同的攻击者不能使用相同的XSS脚本来获取我的XSRF-TOKEN cookie并使用它吗?

To look at it from the other side: local storage is protected by the same-origin-policy just as much as a readable cookie. If I'm using the Auth0 approach, and an XSS attacker knows how to find my JWT in local storage and use it. Can't that same attacker use that same XSS script to grab my XSRF-TOKEN cookie and use that?

这两种攻击都要求他们阅读和理解我的javascript应用程序,但这只是在他们的浏览器中.

Both attacks require them to read and understand my javascript app, but that's out there in their browser.

那有什么区别?一个人真的比另一个人更安全吗?为什么?

So what's the difference? Is one really more secure than another, and why?

推荐答案


_除非您可以防御XSS,否则请放弃所有希望! _


_Abandon all hope unless you can secure against XSS! _

根据其他条件选择适合您的方法,因为两者都同样安全,同样不安全.

如果您使用cookie,则绝对应该使用double-submit-cookie防御或类似的方法,因为它在没有XSS的情况下确实可以保护您免受CSRF的侵害.也就是说,如果您不这样做,那么您肯定会受到来自其他域的CSRF攻击,甚至不需要XSS漏洞就能发挥作用.

If you use cookies, you should definitely use the double-submit-cookie defence, or something similar, because it does protect you against CSRF in the absence of XSS. That is, if you don't do this, you're definitely open to CSRF attacks - from other domains - that don't even require XSS exploits to work.

但是,无论哪种方式,您的源代码都是公开可用的(在您的浏览器中为JavaScript),因此对于有动机的黑客而言,在查找要从本地存储中提取的令牌与读取XSRF-TOKEN Cookie的工作量之间没有显着差异.如果Evil Corp可以在您的域中运行某些JavaScript(即XSS),那么您将无所适从.

But either way, your source code is publicly available (JavaScript in your browser) so for a motivated hacker, there is no significant difference in effort between finding which token to pull from local storage and reading your XSRF-TOKEN cookie. If Evil Corp can get some JavaScript running in your domain - that's XSS - then you're hosed.

  • Cookie很方便,因为您不必编写JavaScript代码即可管理令牌-只需XSRF.

  • Cookies are convenient because you don't have to write JavaScript code to manage the token - only the XSRF.

如果您想使用重定向,重定向也会变得更加自动化.

Redirection becomes a little more automatic too, if you want to use it.

本地存储更易于适应非浏览器应用程序-从服务器的角度来看,因为如果您说的是Java中不想处理cookie的Android应用程序,则服务器不会这样做.不需要在in和浏览器之间进行区分,因为它不使用cookie.

Local storage is easier to adapt to non-browser apps - from the server perspective that is, because if you write say, an Android app in Java that doesn't want to deal with cookies, your server doesn't need to make any distinction between in and the browser, since it's not using cookies.

无论如何,请下定决心,但要小心编写 和使用的第三方JavaScript的JavaScript!

Anyway, make up your own mind, but be careful about the JavaScript you write and the 3rd party JavaScript you use!

这篇关于Cookies是否可以保护令牌免受XSS攻击?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆