met*_*att 248 security cookies csrf owasp web
我试图了解CSRF的整个问题以及预防它的适当方法.(资源我已阅读,理解并同意:OWASP CSRF预防报告表,关于CSRF的问题.)
据我了解,CSRF的漏洞是通过假设(从网络服务器的角度来看)传入HTTP请求中的有效会话cookie反映经过身份验证的用户的意愿而引入的.但是,原始域的所有cookie都被浏览器神奇地附加到请求上,因此实际上所有服务器都可以通过请求中存在的有效会话cookie来推断该请求来自具有经过身份验证的会话的浏览器; 它无法进一步假设该浏览器中运行的代码,或者它是否真正反映了用户的意愿.防止这种情况的方法是在请求中包含其他身份验证信息("CSRF令牌"),这些信息由浏览器的自动cookie处理以外的某些方式携带.然后,松散地说,会话cookie验证用户/浏览器,并且CSRF令牌验证在浏览器中运行的代码.
简而言之,如果您使用会话cookie来验证Web应用程序的用户,您还应该为每个响应添加一个CSRF令牌,并在每个(变异)请求中要求匹配的CSRF令牌.然后,CSRF令牌从服务器到浏览器进行往返回服务器,向服务器证明发出请求的页面是由该服务器批准(甚至由该服务器生成).
关于我的问题,这是关于在该往返中用于该CSRF令牌的特定传输方法.
看起来很常见(例如在AngularJS,Django,Rails中)将CSRF令牌从服务器发送到客户端作为cookie(即在Set-Cookie头中),然后让客户端中的Javascript将其从cookie中删除并附加它作为单独的XSRF-TOKEN标头发送回服务器.
(另一种方法是由例如Express推荐的方法,其中由服务器生成的CSRF令牌通过服务器端模板扩展包含在响应主体中,直接附加到将其提供回服务器的代码/标记,例如作为一个隐藏的表单输入.这个例子是一个更多的Web 1.0-doh的做事方式,但是可以很好地推广给更多JS的客户端.)
为什么使用Set-Cookie作为CSRF令牌的下游传输是如此常见/为什么这是一个好主意?我想所有这些框架的作者都仔细考虑了他们的选择,并没有弄错.但乍一看,使用cookie解决基本上对cookie的设计限制似乎很愚蠢.实际上,如果您使用cookie作为往返传输(Set-Cookie:服务器的下游标头告诉浏览器CSRF令牌,而Cookie:上游标题,浏览器将其返回给服务器)您将重新引入漏洞正试图解决.
我意识到上面的框架不会使用cookie来进行CSRF令牌的整个往返; 他们使用Set-Cookie下游,然后在上游使用其他东西(例如X-CSRF-Token标头),这确实可以关闭漏洞.但即使使用Set-Cookie作为下游传输也可能具有误导性和危险性; 浏览器现在将CSRF令牌附加到每个请求,包括真正的恶意XSRF请求; 充其量只会使请求变得比它需要的更大,而在最坏的情况下,一些善意但误导的服务器代码实际上可能会尝试使用它,这将是非常糟糕的.此外,由于CSRF令牌的实际预期接收者是客户端Javascript,这意味着此cookie不能仅使用http保护.因此,在Set-Cookie标头中向下游发送CSRF令牌对我来说似乎非常不理想.
Sil*_*Fox 236
您接触到的一个很好的理由是,一旦收到CSRF cookie,它就可以在客户端脚本中的整个应用程序中使用,以便在常规表单和AJAX POST中使用.这在JavaScript重型应用程序中是有意义的,例如AngularJS使用的应用程序(使用AngularJS不要求应用程序将是单页面应用程序,因此在状态需要在CSRF值的不同页面请求之间流动时会很有用通常不能在浏览器中持续存在).
在典型应用程序中考虑以下场景和过程,以了解您描述的每种方法的优缺点.这些基于同步器令牌模式.
好处:
缺点:
好处:
缺点:
好处:
缺点:
好处:
缺点:
好处:
缺点:
所以cookie方法是相当动态的,提供了一种简单的方法来检索cookie值(任何HTTP请求)并使用它(JS可以自动将值添加到任何表单中,并且它可以作为标题或作为标题在AJAX请求中使用形式价值).一旦收到会话的CSRF令牌,就不需要重新生成它,因为使用CSRF漏洞的攻击者没有检索此令牌的方法.如果恶意用户尝试使用上述任何方法读取用户的CSRF令牌,则同源策略将阻止此操作.如果恶意用户试图检索CSRF令牌服务器端(例如,通过curl
),则此令牌将不会与同一用户帐户关联,因为请求中将缺少受害者的auth会话cookie(这将是攻击者的 - 因此它赢了不要将服务器端与受害者的会话相关联.
除了Synchronizer Token Pattern之外,还有Double Submit Cookie CSRF预防方法,当然使用cookie来存储一种CSRF令牌.这更容易实现,因为它不需要CSRF令牌的任何服务器端状态.实际上,CSRF令牌可以是使用此方法时的标准身份验证cookie,并且此值通常会像请求一样通过cookie提交,但该值也会在隐藏字段或标头中重复,攻击者无法将其复制为他们首先无法读取价值.除了身份验证cookie之外,建议选择另一个cookie,以便通过标记为HttpOnly来保护身份验证cookie.因此,这是您使用基于cookie的方法找到CSRF预防的另一个常见原因.
Ton*_*gfa 52
使用cookie向客户端提供CSRF令牌不允许成功攻击,因为攻击者无法读取cookie的值,因此无法将其置于服务器端CSRF验证所需的位置.
攻击者将能够使用请求标头中的身份验证令牌cookie和CSRF cookie向服务器发出请求.但是服务器没有在请求头中查找CSRF令牌作为cookie,它正在查看请求的有效负载.即使攻击者知道将CSRF令牌放在有效负载中的哪个位置,他们也必须读取它的值才能将其放在那里.但浏览器的跨域策略阻止从目标网站读取任何cookie值.
相同的逻辑不适用于身份验证令牌cookie,因为服务器期望它在请求标头中,并且攻击者不必做任何特殊的事情来将其放在那里.
我对答案的最佳猜测是:考虑如何将CSRF令牌从服务器下载到浏览器的这3个选项.
我认为第一个,请求正文(虽然我在问题中链接的Express教程演示),但对于各种各样的情况来说并不那么容易; 并非所有人都动态生成每个HTTP响应; 你最终需要在生成的响应中放置令牌的地方可能差异很大(在隐藏的表单输入中;在JS代码的片段中或其他JS代码可访问的变量;甚至可能在URL中看起来通常是一个不好的地方放置CSRF令牌).因此,虽然可以使用一些自定义,但#1是一个难以做到一刀切的方法.
第二个,自定义标头,很有吸引力,但实际上并不起作用,因为虽然JS可以获取它调用的XHR的标头,但它无法获取它加载的页面的标头.
这留下了第三个,一个由Set-Cookie标头携带的cookie,作为一种易于在所有情况下使用的方法(任何人的服务器都能够设置每个请求的cookie头,并且无论何种类型的数据在请求正文中).因此,尽管它有缺点,但它是框架广泛实施的最简单方法.
归档时间: |
|
查看次数: |
98356 次 |
最近记录: |