为什么Play Framework使用[会话ID的签名版本]作为跨站点请求伪造(XSRF/CSRF)预防令牌,而不是会话ID本身?
(使用XSRF预防令牌,我的意思是必须包含在表单提交中的魔术值,以便webapp接受表单.)
如果有窃听者s /他无论如何都会找到XSRF令牌和SID cookie(?).
如果存在XSS攻击,则恶意JavaScript代码可以读取XSRF令牌和SID cookie(?).
然而:
在给定SID的情况下,攻击者无法构造有效的XSRF令牌,因为他/她在签署SID以获取XSRF令牌时没有使用的密钥. - 但是如果攻击者只获得SID而不是XSRF令牌又怎么可能呢?这是牵强附会吗?
如果SID是在HTTP Only cookie中发送的,那么即使他/她找到了XSRF令牌,攻击者也不会拥有SID,并且攻击者可能真的需要SID? - 这是牵强附会吗?
代码片段:
这里Play构造它的XSRF令牌(getId
返回会话ID):( play/framework/src/play/mvc/Scope.java)
public String getAuthenticityToken() { return Crypto.sign(getId()); }
这里Play检查a 是否有一个有效的XSRF令牌:(play/framework/src/play/mvc/Controller.java)
protected static void checkAuthenticity() { if(Scope.Params.current().get("authenticityToken") == null || !Scope.Params.current().get("authenticityToken").equals( Scope.Session.current().getAuthenticityToken())) { forbidden("Bad authenticity token"); } }
更新:
Play改变了生成XSRF令牌的方式,现在不再使用SID,而是签名并使用随机值!(我刚刚将我的Play Framework Git repo克隆从旧的Play版本1.1更新到新版本1.2.也许我应该这样做...昨天,嗯.)
public String getAuthenticityToken() { if (!data.containsKey(AT_KEY)) { data.put(AT_KEY, Crypto.sign(UUID.randomUUID().toString())); } return data.get(AT_KEY); }
那么,他们为什么要做这个改变呢?
我找到了提交:
[#669]再次修复并申请Flash和错误
d6e5dc50ea11fa7ef626cbdf01631595cbdda54c
来自问题#669:
仅在绝对必要时创建会话在
资源的每个请求上创建会话cookie.如果确实存在要在会话中存储的数据,则play应该只创建会话cookie.
所以他们使用的是随机值,而不是SID,因为可能尚未创建SID.那就是不使用SID的衍生物作为XSRF令牌的原因.但是,在过去使用它时,并没有说明为什么他们签署/散列了SID.
首先要说的是,您可以将会话ID重用为CSRF令牌,因为它可以保护您免受CSRF的影响,并且不会自动创建任何严重的安全漏洞.但是,出于某种原因,OWASP曾经明确建议不要这样做.(他们现在根本不解决这个问题.)
反对将会话ID重用为CSRF令牌的论点可归纳如下(粗体的关键点,下面有正当理由):
攻击者获取的会话ID通常比攻击者获取的CSRF令牌更严重的安全漏洞.
攻击者从拥有CSRF令牌获得的所有内容(假设某些其他安全信息,如会话ID,未被重用为CSRF令牌)是执行CSRF攻击的能力.这给了他们两个巨大的限制,如果他们真正获得了一个会话ID,他们就不会有这些限制
他们仍然需要使用相应的会话令牌将用户引诱到攻击页面(或让他们阅读攻击电子邮件,或在iframe中查看攻击广告等)以任何方式利用CSRF令牌.使用会话ID,他们只需要将其放入浏览器中,然后使用该网站,就好像他们是该用户一样.
虽然他们可以使用用户的凭据发送请求,但同源策略仍然阻止他们查看对这些请求的响应.这可能(或可能不是,取决于您保护的API的结构和攻击者的聪明才智)在实践中意味着当攻击者可以代表用户执行操作时,他们无法获取用户有权查看的敏感信息.(您更关心哪些内容取决于具体情况 - 假设攻击者倾向于将您的银行帐户内容仅仅知道这些内容,而且他们也更愿意了解您的病史而非破坏它.)
与会话ID相比,攻击者可能更容易获取CSRF令牌
XSS攻击可能允许攻击者获取CSRF令牌,因为通常的做法是将其烘焙到DOM中(例如,作为一个元素的值,
另一方面,会话cookie可以保密,即使在面对使用HttpOnly标志的成功XSS攻击,要求攻击者提供更多前期工作以有效利用XSS漏洞.
如果CSRF令牌作为请求参数而不是自定义HTTP头发送回服务器(在普通HTML 提交中包含它时保证是这种情况),那么Web服务器访问日志通常会在GET请求上记录CSRF令牌(因为它是URL的一部分).因此,设法查看访问日志的攻击者将能够获得许多CSRF令牌.
将CSRF令牌烘焙到的页面或脚本可以缓存在用户的浏览器中,允许攻击者从缓存中检索它们(例如,在用户使用图书馆或网吧中的公共机器后,可以想象相关)然后清除他们的cookie而不是他们的缓存,或使用"注销"按钮从浏览器中删除他们的会话cookie而不会使服务器端无效).
但是,如果您重新使用会话ID作为CSRF令牌,那么任何允许他们自动获取CSRF令牌的攻击都会为他们提供会话ID.
因此,您不应将CSRF令牌重用为会话ID,因为它会使会话ID更容易受到攻击.
说实话,我认为上面的所有内容都更像是一个理论上的问题,而不是一个实际问题.论证中的弱点是第2点; 我能想到的唯一现实漏洞可用于获取CSRF令牌,但不能用于获取会话cookie仍然是真正严重的漏洞.如果您的站点上有一个XSS漏洞,或者攻击者可以访问您那令人生畏的服务器日志,那么无论如何您都可能完全搞砸了.在我去过的大多数图书馆和网吧中,工作人员并不精通安全,并且很容易安装一个未检测到的键盘记录器,只是收获密码 - 没有必要让攻击者去等待人们使用机器然后翻录浏览器缓存内容的努力.
但是,除非您的情况以某种方式难以为随机会话ID存储CSRF的额外随机令牌,为什么不管它为您带来什么样的安全优势呢?