为什么不使用会话ID作为XSRF令牌?

时间:2011-08-06 16:13:51

标签: security cookies playframework csrf

为什么Play Framework使用[会话ID的签名版本]作为Cross Site Request Forgery(XSRF / CSRF)预防令牌,而不是会话ID本身?

(使用XSRF预防令牌,我的意思是必须包含在表单提交中的魔术值,以便webapp接受表单。)

如果有窃听者s /他无论如何都会找到XSRF令牌和SID cookie。

如果存在XSS攻击,则恶意JavaScript代码可以读取XSRF令牌和SID cookie(?)。

然而:

  1. 在给定SID的情况下,攻击者无法构造有效的XSRF令牌,因为他/她在签署SID以获取XSRF令牌时没有使用的密钥。 - 但是如果攻击者只获得SID而不是XSRF令牌又怎么可能呢?这是牵强附会吗?

  2. 如果SID是在HTTP Only cookie中发送的,那么即使他/她找到了XSRF令牌,攻击者也不会拥有SID,攻击者可能真的需要SID? - 这是不是很牵强吗?

  3. 代码段:

    这里Play构造它的XSRF令牌(getId返回会话ID): (播放/框架/ SRC /播放/ MVC / Scope.java)

        public String getAuthenticityToken() {
            return Crypto.sign(getId());
        }
    

    此处Play检查<form>是否具有有效的XSRF令牌: (播放/框架/ SRC /播放/ 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 Play Git repo克隆从旧版本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。如果确实存在要在会话中存储的数据,则应该只创建会话cookie。

    所以他们使用的是随机值,而不是SID,因为可能尚未创建SID。那就是不使用SID的衍生物作为XSRF令牌的原因。但是,他们在使用SID时,并没有说明为什么他们签署/散列了SID。

3 个答案:

答案 0 :(得分:20)

首先要说的是,可以重复使用会话ID作为CSRF令牌,因为它可以保护您免受CSRF的侵害,并且不会自动造成任何严重的安全漏洞。但是,出于某种合理的原因,OWASP used to explicitly recommend against it。 (他们现在根本不解决这个问题。)

反对将会话ID重新用作CSRF令牌的论点可归纳如下(粗体的关键点,下面有正当理由):

  1. 攻击者获取的会话ID通常比攻击者获取的CSRF令牌更严重的安全漏洞。

    攻击者从拥有CSRF令牌获得的所有内容(假设某些其他安全信息,如会话ID,未被重新用作CSRF令牌)是执行CSRF攻击的能力。这给了他们两个巨大的限制,如果他们真正获得了会话ID,他们就不会有这样的限制:

    • 他们仍然需要使用相应的会话令牌将用户引诱到攻击页面(或让他们阅读攻击电子邮件,或在iframe中查看攻击广告等)以任何方式利用CSRF令牌。使用会话ID,他们只需将其放入浏览器中,然后使用该网站,就好像他们是该用户一样。
    • 虽然他们可以使用用户的凭据发送请求,但Same Origin Policy仍然阻止他们查看对这些请求的回复。这可能(或可能不会,取决于您保护的API的结构和攻击者的聪明才智)在实践中意味着攻击者可以对用户执行操作&#代表他们不能获取用户有权查看的敏感信息。 (您更关心哪些内容取决于具体情况 - 假设攻击者倾向于将您的银行帐户内容仅仅知道多少,但他们也更愿意了解您的病史而不是破坏它。)

  2. 攻击者获取CSRF令牌可能比会话ID更容易

    • XSS攻击可能允许攻击者获取CSRF令牌,因为将其烘焙到DOM中的常见做法(例如,<input><form>元素的值另一方面,会话cookie可以是kept secret even in the face of a successful XSS attack using the HttpOnly flag,要求攻击者提供更多的前期工作,以便有效地利用XSS漏洞。
    • 如果CSRF令牌作为请求参数而不是自定义HTTP头发送回服务器(在普通HTML <form>提交中包含它时保证是这种情况),那么Web服务器访问日志将通常在GET请求上记录CSRF令牌(因为它是URL的一部分)。因此,设法查看访问日志的攻击者将能够获得许多CSRF令牌。
    • 将CSRF令牌烘焙到的页面或脚本可以缓存在用户的浏览器中,允许攻击者从缓存中检索它们(例如,在用户使用公共机器之后,可以认为是相关的)一个图书馆或网吧,然后清除他们的cookie而不是他们的缓存,或者使用“退出”按钮从浏览器中删除他们的会话cookie而不会使服务器端无效)。

  3. 但是,如果您重新使用会话ID作为CSRF令牌,那么任何允许他们自动获取CSRF令牌的攻击都会为他们提供会话ID。 < / p>

  4. 因此,您不应重复使用CSRF令牌作为会话ID,因为它会使会话ID更容易受到攻击。

  5. 说实话,我认为上述所有内容都是理论上的关注而不是实际问题。论证中的弱点是第2点;我能想到的唯一现实漏洞可用于获取CSRF令牌但不能用于获取会话cookie仍然是真正严重的漏洞。如果您的网站上有XSS漏洞,或者攻击者可以访问您的服务器日志,那么您很可能已经完全搞砸了。在我去过的大多数图书馆和网吧中,工作人员并不擅长安全,并且很容易安装一个未检测到的键盘记录器,只是收获密码 - 没有必要攻击者等待人们使用机器,然后翻录浏览器缓存内容。

    但是,除非您的情况以某种方式难以为随机会话ID存储CSRF的额外随机令牌,为什么不管它为您带来什么样的安全优势呢?

答案 1 :(得分:3)

纯粹的CSRF攻击无法访问浏览器的cookie,因此当您说“窃听者”时,如果他们正在嗅探数据包(即没有SSL,公共wifi),那么这只能实现。

根据Play Framework的配置(我不熟悉它,所以把它作为一般的Web应用程序建议),会话和身份验证cookie几乎肯定会被标记为HttpOnly所以他们是无法通过XSS从客户端读取。

最终,使用同步器令牌模式来防止XSRF的想法是使用唯一值(最好是加密强),只有服务器和客户端知道并且该会话是唯一的。基于这个目标,Play Framework似乎做得很好。

答案 2 :(得分:2)

也许Play Framework不希望HTML中的SID。最终用户Bob可能会下载网页,如果该网页中有<form>,则SID将包含在下载的HTML中(如果SID本身用作XSRF令牌)。如果Bob然后将他下载的页面通过电子邮件发送给Mallory,那么Mallory会找到SID并冒充Bob!?

(不使用SID的另一个小原因:正如我在更新中提到的,SID可能根本不可用。也许它是尽可能晚地生成的,以节省CPU资源。)