>情况
examp.le
有一个站点需要花费大量 CPU/RAM 来生成,还有一个更精简的examp.le/backend
,它将执行各种任务来读取、写入和提供用户特定的数据,用于经过身份验证的请求。通过利用examp.le
站点上的服务器端缓存,可以节省大量资源,而不是examp.le/backend
,并且在页面到达客户端后从后端异步获取所有用户特定的数据。(尽管需要额外的请求,但总加载时间甚至可能更短。
威胁模型
CSRF 攻击。假设(也许是愚蠢的(examp.le
可以可靠地防止XSS代码注入,我们仍然需要考虑恶意站点exploit.me
上的脚本,这些脚本会导致受害者浏览器自动包含其授权cookie对examp.le/backend
运行请求,并导致服务器代表用户执行某种数据更改。
解决方案/问题
据我了解,常用的对策是在生成的exampl.le
页面中包含另一个令牌。服务器可以验证此令牌是否已链接到当前用户的会话,并且仅接受可以提供该令牌的请求。但是我认为,如果我们在每个响应中烘焙一个随机令牌,缓存将无法很好地工作examp.le
..?
那么...
我看到了两种可能的解决方案:一种是某种"混合缓存",其中对examp.le
的每个响应仍然是以编程方式生成的,但该程序只是将小的动态部分合并到一些缓存的输出中。不适用于在服务器堆栈的较高层上运行的缓存系统,更不用说 CDN,但仍然可能有其优点。我不知道是否有标准的方法或库来做到这一点,或者更具体地说,是否有 wordpress 的解决方案(这恰好是我的情况的罪魁祸首(。
另一个(首选(解决方案是直接从examp.le/backend
获取初始的反CSRF令牌。但我不太清楚我对此的含义的理解。如果exploit.me
上的脚本可以以某种方式获得该令牌,那么整个机制将毫无意义。我的理解是,如果我们把可利用的浏览器错误和安全漏洞排除在外,只考虑来自访问exploit.me
的非晦涩浏览器的请求,那么绝对可以信任HTTP_ORIGIN
标头是防篡改的。这是对的吗?但这就引出了一个问题:在这种情况下,我们是否可以通过只检查身份验证 cookie 和源标头而不来回抛出令牌来获得基本相同的安全性?
如果这个问题感觉有点到处都是,我很抱歉,但我部分仍在了解整个画面的过程中;-(
首先:跨站点脚本(XSS(和跨站点请求伪造(CSRF(是两种不同的攻击类别。我假设,你的意思只是解决CSRF问题。
其次:了解CSRF是什么是至关重要的。请考虑以下操作。
- 用于
exampl.le/backend
更改某种关键数据的 POST 请求 - 对
exampl.le/backend
的请求受身份验证机制保护,这些机制会生成有效的会话 Cookie。 - 我想攻击你。我通过向您发送指向我在
cats.combest_cats_evr
伪造的页面的链接来做到这一点。 - 如果您在一个浏览器选项卡中登录以
exampl.le
,并在另一个浏览器中打开cats.combest_cats_evr
,则将执行代码。 - 站点上的代码
cats.combest_cats_evr
将向exampl.le/backend
发送 POST 请求。饼干将被附加,因为没有理由不应该。您将在不知情的情况下对exampl.le/backend
执行更改。
那么,话虽如此,我们如何防止此类攻击?
CSRF案例在社区中非常熟悉,我自己写下所有内容是没有意义的。请查看OWASP CSRF预防备忘单,因为它是您可以在本主题中找到的最佳页面之一。
是的,在这种情况下检查原点会有所帮助。但是检查原点将无济于事,如果我在exampl.le/somewhere_else
中发现XSS漏洞并将其用于对付您。
同样有帮助的是不使用 POST 请求(因为它们可以在没有源检查的情况下进行操作(,而是在 CORS 应该提供帮助的地方使用 PUT......但这很快就会被证明是开发团队无法处理的火箭科学,并且坚持使用旧的反CSRF代币(每个框架默认支持(应该会有所帮助。