【问题标题】:ETags for server-side rendered pages that contain CSP nonce包含 CSP 随机数的服务器端呈现页面的 ETag
【发布时间】:2019-03-05 13:09:04
【问题描述】:

我有一个服务器端渲染的 React 应用程序,到目前为止,Node/Express 能够生成正确、稳定的ETags,从而可以利用客户端缓存。

此外,生成的 HTML 包含渲染阻止(首屏)CSS 和 JS 内联 的片段,作为 <script><style> 标记,用于更快的客户端首次渲染(如宣传的那样) Google 及其 PageSpeed 和 Lighthouse 工具)。

现在我想启用Content Security Policy (CSP),并为每个页面请求上的<script><style> 标记提供nonce 作为属性,以避免unsafe-inline 违规。然而,不断变化的 nonce 使得 ETags 也随着每个请求而改变。 HTML 永远不会被缓存,每个请求都会到达我的 Express 服务器。

有没有办法同时结合:

  • 内联 CSS 和 JS
  • CSP 功能(即nonce 或类似功能)
  • ETag 或替代品

?

到目前为止,我发现当前性能与安全准则之间存在矛盾。

是否有 CSP nonce 的等价物,或者是否可以在保持 HTML 完整的同时提供 CSP nonce?有没有办法缓存包含 CSP 随机数的页面?

理想情况下,我希望在 Express 服务器中包含一个解决方案,而无需修改我的反向代理配置,但欢迎任何选项。

【问题讨论】:

  • 我认为使用哈希而不是随机数将是处理这个问题的方法。
  • @KevinChristopherHenry 谢谢。事实上,scrpt-src '<hash-algorithm>-<base64-value>' 可能是一条路。你知道 CSP 哈希与SRI 相比如何吗?浏览器支持怎么样?完全放弃 nonce 有点吓人。当然是安全/性能权衡。
  • 我对浏览器支持没有任何特别的见解,但MDN 表明它与 nonces 具有相同的支持(即 CSP 2.0 的一部分)。我没有看到任何安全方面的缺点,加密哈希非常安全(也就是说,攻击者插入另一个具有相同哈希值的内联脚本是不可行的)。
  • 至于随机数与散列的使用,csp.withgoogle.com/docs/strict-csp.html 建议使用随机数——并且隐含地优先于散列——尽管csp.withgoogle.com/docs/faq.html#static-content 解释了如何在随机数不能使用的情况下使用散列使用。但另请参阅 w3c.github.io/webappsec-csp/#security-considerations,其中包含一些关于使用 nonces 的警告。
  • @sideshowbarker 好收获!到目前为止,似乎最好同时使用哈希和随机数。这意味着 ETag 正在失去市场。也许我只是摆脱它们并为 Express 提供更多计算 :)
    添加另一个论点来捍卫随机数:当脚本内容是动态时,您不能使用散列 (link)。动态脚本内容在很多方面都是错误的,我没有,但谁知道呢,也许他们有有效的用例。

标签: html express browser-cache content-security-policy etag


【解决方案1】:

一种解决方案是将整个内容生成和缓存留给 Web 应用程序(在您的情况下为 Node),将 CSP 随机数生成留给前端 Web 服务器(例如 Nginx)。我已经用 Django 实现了它,它使用 ETag 进行页面缓存,执行所有 Vary 标头逻辑等,它生成的 HTML 包含这样一个静态 CSP 随机数占位符:

< script nonce="+++CSP_NONDE+++"> ... </script>

这个占位符然后由 Nginx 使用 ngx_http_subs_filter_module 填充:

sub_filter_once off;
sub_filter +++CSP_NONCE+++ $ssl_session_id;
add_header Content-Security-Policy "script-src 'nonce-$ssl_session_id'";

我见过使用额外的 Nginx 模块为每个请求生成真正唯一的随机随机数的解决方案,但我认为这有点过头了,我只是使用 TLS 会话标识符,它对于每个连接的客户端都是唯一的,并且可能会被缓存一段时间(例如 10 分钟),具体取决于您的 Nginx 配置。

只要确保 Web 应用程序返回未压缩的 HTML,因为 Nginx 将无法进行字符串替换。

【讨论】:

    猜你喜欢
    • 2020-01-02
    • 2021-04-20
    • 1970-01-01
    • 1970-01-01
    • 2020-12-11
    • 1970-01-01
    • 1970-01-01
    • 2021-05-18
    • 1970-01-01
    相关资源
    最近更新 更多