如何将 CSRF 令牌从服务器传递到客户端?
How to pass CSRF token from server to client?
这听起来像是一个愚蠢的问题。我想弄清楚这一点。如果先将令牌发送给客户端,然后客户端发回相同的令牌,csrf 令牌如何帮助识别跨站请求?恶意客户端不会得到服务器的响应。
如果我们在发送令牌的同时检查来源,那么令牌检查的东西是不是显得多余?
我们如何确定服务器只会将令牌提供给授权客户端,以及将令牌从服务器传输到客户端的最佳做法是什么?
我问了一个相关问题 但需要更深入地了解它。所以在这里问一个不同的问题。
希望通过示例得到一些答案。
提前致谢
CSRF 基本上是关于攻击者通过 cookie 在浏览器中的工作方式利用用户现有的 session。潜在的问题是无论请求来自哪里(哪个来源,即域)来自,cookie 都会随请求一起发送,唯一重要的是它的去向到。因此,如果有用户登录到应用程序(具有 session cookie),攻击者可能会尝试让该用户访问他的恶意网站,攻击者可以从那里向应用程序域发出请求凭据(通过将用户完全发布到应用程序,或者更巧妙地通过创建 ajax 请求)。
请注意,这仅适用于应用程序中的身份验证基于浏览器自动发送的内容,最明显的是 session cookie,但例如基本的 http 身份验证或客户端证书身份验证也可能易受伤害的。此外,CSRF 仅适用于更改某些内容(状态或数据)的请求。
有一件重要的事情在起作用,同源策略 (SOP) 是浏览器。稍微简化一下,这意味着如果从一个域(或更准确地说:来源)下载某些内容,则另一个域将无法访问。
因此,为了防止上述攻击并防止攻击者在他自己的域上让用户向用户登录的应用程序发送不需要的请求,可能有几种不同的策略。
同步器令牌
应用程序生成一个csrf令牌,将其存储在用户的session(server-side)中,并通过例如将其写入隐藏字段中的每个表单发送给客户端,或者在 Javascript 可以从中读取并添加到请求中的一个字段中。这是可行的,因为他的域中的攻击者无法使用用户 session 中的有效令牌创建表单或请求,并且攻击者也无法从应用程序页面读取令牌。当然,攻击者可以尝试下载申请表来获取令牌,但他需要凭据。攻击者需要有效用户的 session 和相应的 csrf 令牌。攻击者可能有自己合适的帐户登录,但无论如何他都可以执行该操作。或者他可能有一个 csrf 令牌,但要么未经身份验证,要么属于权限较低的帐户。但他不能两者兼得,这就是重点。
所以这种保护基本上验证了请求来自合法应用程序实际呈现的来源,而不是其他人。
请注意,在这种情况下,在 cookie 中设置令牌是没有意义的,因为 cookie 将像 session cookie 一样自动发送。
双posting
另一种策略是生成令牌,并将其设置为客户端的 cookie。然后客户端从 cookie 中读取令牌,并发送相同的令牌作为请求 header。服务器只比较请求header和cookie是否包含相同的token。这是可行的,因为攻击者无法从不同来源设置的 cookie 中读取应用程序令牌(请参阅上面的 SOP),但合法域上的应用程序可以。所以发送请求的客户端有效地证明了它是合法应用域上的运行。这样做的好处是应用程序是无状态的,不需要session。缺点是它的安全性稍差。
(有趣的是,这种情况下的令牌甚至可以在客户端生成,它仍然有效,因为在他自己的域上的攻击者无法设置或读取应用程序域cookie,但它确实不太安全浏览器中的加密操作。)
检查引荐来源或来源
正如您正确指出的那样,另一种策略可能是检查请求的引荐来源或来源。它基本上可以工作,但被认为不太安全。虽然双 posting 被认为对许多应用程序来说足够安全,但 referer/origin 检查大多不是。我认为它有很强的历史因素,但它确实 不太安全。
问题有很多方面,我想到了一些:
- 攻击者在他自己的域上发送referer/origin header can be prevented。所以应用程序不会知道它是一个不同的域——它只是没有信息。您当然可以以需要引用 and/or 来源的方式实现它,但这会导致潜在的错误和浏览器由于某种原因不发送它等问题
- Referer 和 origin 在某些情况下是可以伪造的。例如,旧的易受攻击的浏览器插件(Java、Flash...还有人记得 Flash 吗?)允许设置任何 header,攻击者只需要在受害者浏览器中安装其中一个 - 每个人有它们。
- 浏览器扩展也可以 set/modify headers,因此攻击者可能会尝试e 他的恶意扩展由受害者用户安装。
- Origin 仅由现代浏览器设置。现在问题不大了,大多数人使用的浏览器都设置了 referer 和 origin。
因此,由于这些原因,简单地检查 referer/origin 不是很稳健,应该有另一层保护。
SameSite cookies
Google 在 Chrome 中的一项新发明是 cookie 的 SameSite
属性(除了已经存在且广泛使用的 httpOnly
和 secure
cookie 属性)。截至目前,只有 Chrome 支持,其他浏览器不支持。
如上所述,潜在的问题是 cookie(即 session cookie)根据请求目标而不是来源发送到服务器。这意味着如果 attacker.com 将页面服务器发送给用户,并且该页面从浏览器向 legitapp.com 发送 post 请求,则 legitapp.com 设置的任何 cookie 都将发送到 legitapp.com。所以如果是登录legitapp.com的用户访问attacker.com,现有的session就可以被利用
这已被 SameSite cookie attribute 更改,这使得在原始域与目标域不同的情况下不会发送 cookie。它可以设置为 'strict' 或 'lax',这基本上决定了 GET 请求的行为,但其中任何一个都会阻止 CSRF on
non-GET 个请求。
这听起来像是一个愚蠢的问题。我想弄清楚这一点。如果先将令牌发送给客户端,然后客户端发回相同的令牌,csrf 令牌如何帮助识别跨站请求?恶意客户端不会得到服务器的响应。
如果我们在发送令牌的同时检查来源,那么令牌检查的东西是不是显得多余?
我们如何确定服务器只会将令牌提供给授权客户端,以及将令牌从服务器传输到客户端的最佳做法是什么?
我问了一个相关问题
希望通过示例得到一些答案。
提前致谢
CSRF 基本上是关于攻击者通过 cookie 在浏览器中的工作方式利用用户现有的 session。潜在的问题是无论请求来自哪里(哪个来源,即域)来自,cookie 都会随请求一起发送,唯一重要的是它的去向到。因此,如果有用户登录到应用程序(具有 session cookie),攻击者可能会尝试让该用户访问他的恶意网站,攻击者可以从那里向应用程序域发出请求凭据(通过将用户完全发布到应用程序,或者更巧妙地通过创建 ajax 请求)。
请注意,这仅适用于应用程序中的身份验证基于浏览器自动发送的内容,最明显的是 session cookie,但例如基本的 http 身份验证或客户端证书身份验证也可能易受伤害的。此外,CSRF 仅适用于更改某些内容(状态或数据)的请求。
有一件重要的事情在起作用,同源策略 (SOP) 是浏览器。稍微简化一下,这意味着如果从一个域(或更准确地说:来源)下载某些内容,则另一个域将无法访问。
因此,为了防止上述攻击并防止攻击者在他自己的域上让用户向用户登录的应用程序发送不需要的请求,可能有几种不同的策略。
同步器令牌
应用程序生成一个csrf令牌,将其存储在用户的session(server-side)中,并通过例如将其写入隐藏字段中的每个表单发送给客户端,或者在 Javascript 可以从中读取并添加到请求中的一个字段中。这是可行的,因为他的域中的攻击者无法使用用户 session 中的有效令牌创建表单或请求,并且攻击者也无法从应用程序页面读取令牌。当然,攻击者可以尝试下载申请表来获取令牌,但他需要凭据。攻击者需要有效用户的 session 和相应的 csrf 令牌。攻击者可能有自己合适的帐户登录,但无论如何他都可以执行该操作。或者他可能有一个 csrf 令牌,但要么未经身份验证,要么属于权限较低的帐户。但他不能两者兼得,这就是重点。
所以这种保护基本上验证了请求来自合法应用程序实际呈现的来源,而不是其他人。
请注意,在这种情况下,在 cookie 中设置令牌是没有意义的,因为 cookie 将像 session cookie 一样自动发送。
双posting
另一种策略是生成令牌,并将其设置为客户端的 cookie。然后客户端从 cookie 中读取令牌,并发送相同的令牌作为请求 header。服务器只比较请求header和cookie是否包含相同的token。这是可行的,因为攻击者无法从不同来源设置的 cookie 中读取应用程序令牌(请参阅上面的 SOP),但合法域上的应用程序可以。所以发送请求的客户端有效地证明了它是合法应用域上的运行。这样做的好处是应用程序是无状态的,不需要session。缺点是它的安全性稍差。
(有趣的是,这种情况下的令牌甚至可以在客户端生成,它仍然有效,因为在他自己的域上的攻击者无法设置或读取应用程序域cookie,但它确实不太安全浏览器中的加密操作。)
检查引荐来源或来源
正如您正确指出的那样,另一种策略可能是检查请求的引荐来源或来源。它基本上可以工作,但被认为不太安全。虽然双 posting 被认为对许多应用程序来说足够安全,但 referer/origin 检查大多不是。我认为它有很强的历史因素,但它确实 不太安全。
问题有很多方面,我想到了一些:
- 攻击者在他自己的域上发送referer/origin header can be prevented。所以应用程序不会知道它是一个不同的域——它只是没有信息。您当然可以以需要引用 and/or 来源的方式实现它,但这会导致潜在的错误和浏览器由于某种原因不发送它等问题
- Referer 和 origin 在某些情况下是可以伪造的。例如,旧的易受攻击的浏览器插件(Java、Flash...还有人记得 Flash 吗?)允许设置任何 header,攻击者只需要在受害者浏览器中安装其中一个 - 每个人有它们。
- 浏览器扩展也可以 set/modify headers,因此攻击者可能会尝试e 他的恶意扩展由受害者用户安装。
- Origin 仅由现代浏览器设置。现在问题不大了,大多数人使用的浏览器都设置了 referer 和 origin。
因此,由于这些原因,简单地检查 referer/origin 不是很稳健,应该有另一层保护。
SameSite cookies
Google 在 Chrome 中的一项新发明是 cookie 的 SameSite
属性(除了已经存在且广泛使用的 httpOnly
和 secure
cookie 属性)。截至目前,只有 Chrome 支持,其他浏览器不支持。
如上所述,潜在的问题是 cookie(即 session cookie)根据请求目标而不是来源发送到服务器。这意味着如果 attacker.com 将页面服务器发送给用户,并且该页面从浏览器向 legitapp.com 发送 post 请求,则 legitapp.com 设置的任何 cookie 都将发送到 legitapp.com。所以如果是登录legitapp.com的用户访问attacker.com,现有的session就可以被利用
这已被 SameSite cookie attribute 更改,这使得在原始域与目标域不同的情况下不会发送 cookie。它可以设置为 'strict' 或 'lax',这基本上决定了 GET 请求的行为,但其中任何一个都会阻止 CSRF on non-GET 个请求。