我是现代浏览器支持的内容安全策略范例 (CSP) 的大力支持者。事实上,我非常喜欢它们,我什至编写了一个 Pluralsight 课程: 浏览器安全标头简介 。 (旁注:我对这门课程的接受程度感到 非常 高兴,似乎毕竟有保护我们的东西的胃口!)
现在,如果您不确定所有这些大惊小怪的事情,请快速阅读 我的课程发布博客文章 。这很好地概述了为什么 CSP(以及其他标头)很棒。写下所有关于标题如何工作的内容应该意味着我知道我在用它们做什么,对吧?是的,关于那个……
我想分享这个来证明虽然很棒,但很容易打破你意想不到的东西。请记住,CSP 的整体理念是将您认为良好的各种类型数据的来源列入白名单。如果您忘记将 CSP 标头中的某些内容列入白名单,识别该标头的浏览器将不会加载它。让我通过向您展示这张 我被伪造 (HIBP) 状态页面 的图像来演示:
现在你应该注意到两件事:
- 您正在我的 iPad 上查看在 Safari 中加载的页面
- 你没有看太多 - 屏幕上有一个大白框,应该出现 New Relic 图表
这很好奇,因为它在我的机器上运行良好(著名的遗言),或者至少在 我的 PC 上运行良好。然后有人对我说了一句“伙计,你的网站坏了”,在强制性的“不是我,是你”的讨论之后,我决定进一步探索。
我首先通过 Fiddler 代理 iPad( 也有一门课程! ),然后我在设备上加载了状态页面。这是我发现的:
三个突出显示的请求都开始出错。这些是 CSP 违规报告,当出现问题时,浏览器将其发送回 CSP 标头中声明的 report-uri 路径。那是三份报告,三份遗失的 New Relic 图表,这里开始有什么味道了……
现在关于 CSP 违规报告的巧妙之处在于它们会解释出了什么问题,因为它们包含如下请求正文:
在这种情况下,我们可以看到 New Relic URL https://rpm.newrelic.com 在 https://haveibeenpwned.com/Status 页面上被阻止,因为它违反了“default-src 'self'”指令。现在这很奇怪,因为这些图表是如何嵌入到页面中的:
<iframe src="https://rpm.newrelic.com/public/charts/loQTOR6Umg7" scrolling="no" frameborder="no"></iframe>
之所以奇怪,是因为 New Relic URL 是 iframe 的来源,并且已经使用此指令在我的 CSP 中列入白名单:
<iframe src="https://rpm.newrelic.com/public/charts/loQTOR6Umg7" scrolling="no" frameborder="no"></iframe>
发生什么了?对于所有棘手的 CSP 问题,我求助于 Scott Helme ,结果发现他的博客文章 Safari doesn't like CSP 的 标题非常恰当。 Scott 在那里谈到了 Apple 浏览器的一些特性,当他听说我的 iPad 正在做什么时,他并没有感到太惊讶。事实证明,解决方案非常简单:
<iframe src="https://rpm.newrelic.com/public/charts/loQTOR6Umg7" scrolling="no" frameborder="no"></iframe>
呃,那好吧,为什么?首先, 这是 frame-src 指令的实际作用 :
哦,等等,它已被弃用,让我们改用 child-src。哦不,现在在Safari里坏了,还是用frame-src吧。该死的,它被弃用了,让我们使用……
答案是同时使用 child-src 和 frame-src,并忍受冗余声明(包括弃用指令)的代码恶臭。该死的。这很烦人,但这可以立即修复它,现在它看起来像这样:
这是 CSP 的许多特质之一,但这是我想留给您的真实信息: 即使您“正确”配置 CSP,它也可能会破坏您的东西 。我的 CSP 完全符合规范,但由于 Safari 无法识别商定的标准,所以它失败了。通常我会告诉人们不要担心,如果您添加了 CSP,然后有人带着无法识别它的浏览器过来,因为它会忽略它。但是实际上,由于浏览器实施不当,您 可能会 破坏您的网站,尽管这对我来说只是一个小小的不便,但我并不真正高兴它首先发生了。
这里有一条明智的建议:监控您的 CSP 报告。我记录了报告,但没有主动监控它们。实际上,Scott 在 report-uri.io 上有一项免费为您做这件事的服务。您将报告发送到那里,然后他将它们记录下来并提供给审查。我没有使用他的 HIBP 服务的唯一原因是我不愿意将人们的数据发送到外部服务,即使这只是 不应该 发生的违规报告,也不会透露任何超出你在网站上看到的内容上面的违规报告(以及用户的 IP 地址和请求标头,Scott 根据 他的 FAQ 都没有记录)。
但现在我正在重新考虑,因为我应该早点发现这个问题,所以你怎么看——我应该将 HIBP 报告发送到 report-uri.io 吗?请在评论中留下您的想法,如果人们不认为这是隐私问题而得到足够的支持,我将转而使用 Scott 的服务,并希望早日解决类似的未来问题。