Defaults.Exposed

Defaults.Exposed修复 › 内容安全策略(CSP)

如何修复 内容安全策略(CSP)

内容安全策略是你的网站交给每个访客浏览器的一条安全规则,明确告诉它哪些代码获准运行。没有它,一旦有恶意东西落到页面上——通过一个评论框、一个被黑的插件,或一个第三方脚本——浏览器就会随意运行它,包括在你客户输入时悄悄盗取卡号和密码的代码,而那把锁还显示着。

对您业务的关键影响: 你的网站一旦被篡改,恶意代码就能在一切看起来完全正常的情况下,直接从你自己的结账页面读走客户的支付卡和登录信息——留给你的是退款、欺诈索赔、一桩须上报的数据泄露,以及一个大客户安全团队用来搁置或扼杀生意的检查失败。

这会让您付出什么代价

为什么它重要。 那把锁证明到你网站的连接是私密的,但它对访客上了页面之后哪些代码运行毫无控制。内容安全策略正是那个有控制的防护——它告诉浏览器忽略任何并非来自你信任来源的脚本,于是一个被篡改的字段、广告或插件,无法被变成盗取你客户金钱和数据的工具。它是你评分卡上的一项计分检查,值实打实的分数,也是一次专业安全审查最先查的东西之一。

这是什么,大白话版

当有人访问你的网站时,他的浏览器下载你的页面并运行上面的任何代码——那些让菜单下拉、按钮工作、支付表单提交等等的脚本。默认情况下,浏览器信任所有这些。它无从知道哪些代码真正是你的、哪些是别人偷偷塞进来的。

一个内容安全策略(常简称 CSP)是你的网站附加到每个页面上的一份简短规则清单,告诉浏览器:「只运行来自我批准的这些来源的代码,其余一概拒绝。」 这是一家谁都放进去的夜店和一家门口有宾客名单的夜店之间的区别。

它之所以如此重要,是因为网站不断被篡改——并不总是通过黑掉你的服务器,而是通过多数网站留着的那些后门:一个评论字段、一个搜索框、一个过时的插件、一个用于广告或分析的第三方脚本,或一个聊天小部件。如果攻击者哪怕把一行他自己的代码弄到你的某个页面上,浏览器就会把它当作你的来运行。从那里它能读走你客户输入的一切——卡号、密码、地址——并悄悄送往别处。内容安全策略通过拒绝运行任何来自你未批准来源的东西,关上那扇门。

这会让你付出什么代价

这不抽象。内容安全策略所防止的攻击——注入页面、从你自己客户那里盗取数据的代码——是有记录以来一些最大的刷卡泄露的幕后元凶。下面是它对一家普通企业往往如何上演:

它到底是什么(细节)

一个内容安全策略以一个 HTTP 响应头的形式传递——一行你的 Web 服务器随每个页面发送的内容。它的值是一组指令,每条命名一类内容及其允许的来源。例如:

Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; frame-ancestors 'self'

用大白话说,这是:默认只从我自己的网站加载东西;只运行来自我自己网站的脚本;不允许任何老式插件;并且不让其他网站把我的网站嵌进一个框架里。

「好」长什么样。 我们的检查不只是看头是否存在——它像一个安全审查者那样,逐条指令地读这个策略,给它实际有多强评分。一个强壮的策略:

一个存在却依赖 'unsafe-inline''unsafe-eval' 或通配符的策略仍会得分很低——因为实际上它提供的真实保护很少。目标是一个收紧的策略,而不只是随便一个策略。

如何修复(免费,约 1–2 小时)

把这个交给你的 IT 人员或运营你网站的人——修复本身完全免费。 我们只对长期监控它是否保持就位、保持正确收费;打开它分文不取。它要花一两个小时而非几分钟的原因,是那个防止它不小心拦掉你自己网站某些部分的小心试运行步骤。

  1. 以仅报告模式起步——暂不强制执行。 添加一个 Content-Security-Policy-Report-Only 响应头。它观察并记录「会被」拦掉什么,却不真正拦截任何东西,于是实时网站照常工作,同时你了解每个页面真正依赖什么。(重要:仅报告本身不给访客任何保护——它只是稳妥的第一步。)

  2. 从你网站实际使用的东西出发构建策略。 审查报告,找出每一个合法的脚本、样式、字体和图片来源——你自己的域名、你的分析、你的支付服务商、你的字体托管、你的聊天小部件——把它们列为允许的来源。一个扎实的起点是 default-src 'self' 加上你真正使用的可信第三方的显式条目。

  3. 避开那些击穿整个意义的漏洞。 远离脚本的 'unsafe-inline''unsafe-eval',并避免脚本的通配符来源如 * 和光秃秃的协议如 https:——这些重新打开了策略本该关上的那个缺口。在内联脚本不可避免的地方,使用一个 noncehash,让只有你特定批准的代码才运行。

  4. 锁死框架嵌入和插件。 加上 frame-ancestors 'self'(这也阻止其他网站嵌入你的来诓骗你客户,并满足相关的点击劫持检查)和 object-src 'none' 来拦截基于遗留插件的攻击。

  5. 从仅报告切换到强制执行。 一旦报告干净、网站工作,就把头名称从 Content-Security-Policy-Report-Only 改成 Content-Security-Policy这一步才真正交付保护——单有一个仅报告策略并不交付,也不会通过检查。

    你在哪里设这个头取决于你的平台:

    • Cloudflare: Rules → Transform Rules → Modify Response Header → 设 Content-Security-Policy。(你也可以用 Cloudflare 做仅报告试运行。)
    • Nginx: add_header Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; frame-ancestors 'self';" always;
    • Apache: Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; frame-ancestors 'self';"
    • IIS(web.config): 添加一个名为 Content-Security-Policy 的自定义 HTTP 响应头,以策略为其值。
    • Google Workspace / Microsoft 365: 这些运行的是你的邮件,不是你的公开网站,所以策略设在你网站实际托管的地方(上面的 Cloudflare 或你的 Web 主机),而不是你的邮件管理后台。
  6. 重新检测你的域名,确认策略现在显示为已打开、且在强制执行,没有削弱性的漏洞。

常见错误

常见问题

我不懂技术——这个我自己能搞定吗?

你不需要懂细节。这是由运营你网站或主机的人添加的一个设置,而在 Cloudflare 这样的服务上它基本是有引导的。把下面的「如何修复」一节交给他们。它免费;唯一要当心的是,它应当先以仅观察的试运行小心铺开,以免不小心拦掉你自己网站的某些部分——而那恰恰是这些步骤所涵盖的。

我已经有那把锁和一张 SSL 证书了——我的网站不就安全了吗?

那把锁保护你页面的「传输」;它不管页面「里面」运行什么。一旦恶意代码落到页面上——通过一个被黑的插件、一个被攻陷的广告,或一个被注入的字段——那把锁不会阻止它盗取数据。内容安全策略是那个从一开始就限制允许运行什么的层。它们保护不同的东西,你两个都要。

打开这个会搞坏我的网站吗?

如果一次性激进地打开就有可能,因为它可能拦掉你实际使用的合法脚本。这正是为什么标准做法是先以「仅报告」试运行模式起步,它观察而不拦截,修好它标记的任何东西,然后才强制执行。这样做是安全的——而这个试运行步骤已内置在下面的修复里。

我们已经把它放在「仅报告」模式了——这就被覆盖了吗?

没有,而这是最常见的虚假安全感。仅报告模式观察并记录「会被」拦掉什么,但它什么都不拦——访客得到的真实保护为零。它只是稳妥的第一步。我们的检查只给仅报告一个真实策略的一小部分信用,并且不会把它记为通过。你只有切换到强制执行模式后才受保护。

这影响我们的评分,还是只是建议性的?

它影响你的评分。内容安全策略检查是计分的,在网站安全类别中最高值 25 分。一个缺失或孱弱的策略被标为高严重度,会拉低你的评分——而它恰恰是一个客户的安全问卷会问到的那类缺口。

我们的开发者加了一个策略,但分数还是很低——为什么?

一个策略可以存在却仍然孱弱。最常见的祸首是像脚本的「unsafe-inline」和「unsafe-eval」之类的漏洞,或通配符来源(一个光秃秃的 *),它们重新打开了策略本该关上的那个缺口。我们的检查逐条指令地读这个策略,并对那些弱点扣分——一个什么都允许的策略,得分比没有策略好不了多少。修复是用 nonce 或 hash 来收紧脚本规则,而不是那些漏洞。