什么是 CSP?为何以及如何将其添加到您的网站。

2025-06-07

什么是 CSP?为何以及如何将其添加到您的网站。

跨站脚本 (XSS) 糟透了!XSS 是指有人通过评论、表单、广告或 JavaScript 构建中的 NPM 包,将 JavaScript 或 CSS 偷偷带入你的网站。现在,他们掌握了所有访问你网站的用户的账户。XSS 是一种非常常见的攻击,OWASP 声称每 3 个网站和应用中就有 2 个会遭遇这种攻击

您可以使用 CSP(内容安全策略)来消除大多数 XSS 攻击。CSP 允许您列出允许的外部和内部脚本、样式、图像和其他内容源。它甚至兼容所有主流浏览器

既然 CSP 可以拦截已知的最常见攻击之一,你以为每个人都会使用它吗?不是的!访问量最大的一百万个网站中,只有不到 2.5% 使用它

呆伯特漫画。点击链接查看文字记录。

对于大多数网站来说,安全都是事后才考虑的,直到有人窃取了他们的所有数据。然后公众在社交媒体上愤怒不已。典型的公司反应是解雇员工,并承诺将安全放在首位,同时在背后祈祷安全。

让我们看看如何才能避免这样的混乱。

如何添加 CSP 策略

第一步是向您的服务器配置添加一个标头。建议从尽可能严格的 CSP 规则开始,但将其设置为“仅报告”模式。这会创建一份报告,说明如果我们屏蔽所有可能的流量,将会发生什么情况。获得报告后,您就可以开始选择要允许的项目(也称为白名单)、要为哪些项目创建备用修复程序以及要屏蔽哪些项目。

以下是建议的起始标题:

Content-Security-Policy-Report-Only: default-src 'none'; form-action 'none'; frame-ancestors 'none';
Enter fullscreen mode Exit fullscreen mode

将 CSP 添加到您的网站后,您可以使用浏览器开发人员工具来查看它和任何其他标题。在浏览器的开发人员工具中查看您的页面时,您的 CSP 应该与其他标题一起出现。

如果我们没有将其设置为报告模式,您将看到“CSP 的全部威力!”换句话说,CSP 会阻止您的大部分网站。

请记住,内容安全策略 (CSP) 的作用是阻止所有您不允许的内容。

如果你在浏览器开发者工具(F12)中打开控制台,通常会看到很多错误。第一个错误可能会提示缺少 report-uri,但我们稍后会讨论这个问题。其余错误都应该以 [Report Only] 开头。这是 CSP 报告模式,它会告诉你哪些内容会被拦截以及如何允许拦截。

CSS样式表通常是最先出现的错误之一。它看起来像这样:

[Report Only] Refused to load the stylesheet 'https://example.com/style.css' because it violates the following Content Security Policy directive: "default-src 'none'". Note that 'style-src' was not explicitly set, so 'default-src' is used as a fallback.
Enter fullscreen mode Exit fullscreen mode

为了解决这个问题,我们调整了策略,添加了允许“self”的 style-src 指令。添加“self”允许我们包含任何与页面托管在同一 URL 和端口号上的 CSS 样式表。如果不这样做,style-src 将默认使用我们已设置为 none 的 default-src 指令。

Content-Security-Policy-Report-Only: default-src 'none'; form-action 'none'; frame-ancestors 'none'; style-src 'self';
Enter fullscreen mode Exit fullscreen mode

您很可能还想在图像和脚本中添加“self”。这将导致再次调整我们的 CSP。

Content-Security-Policy-Report-Only: default-src 'none'; form-action 'none'; frame-ancestors 'none'; style-src 'self'; script-src 'self'; img-src 'self';
Enter fullscreen mode Exit fullscreen mode

典型的网站也需要依赖外部脚本。我们可以通过修改 script-src 指令来允许来自域名cdnjs.com的 JavaScript 运行。

Content-Security-Policy-Report-Only: default-src 'none'; form-action 'none'; frame-ancestors 'none'; style-src 'self'; script-src 'self' cdnjs.com; img-src 'self';
Enter fullscreen mode Exit fullscreen mode

看到我们当前的规则,你可能会想,为什么我们要明确声明 form-action 和 frame-ancestors 的指令?它们是特殊情况,不使用 default-src 后备。

您可以在MDN上找到完整的指令列表

内联脚本是我的中间名

内联 JavaScript 和 CSS 在网站上经常使用,但它们也很危险。它们是黑客发起 XSS 攻击的最简单方法。因此,要允许它们,您必须在'unsafe-inline'要允许它们的指令中添加。这是为了确保您了解自己正在做什么,不建议这样做。

一种常见的 CSS 模式是将渲染“首屏内容”的最重要的 CSS 代码与<style>标签内联。这有助于减少感知到的渲染时间。对于HTTP/2,我通常不建议这样做,因为它通常会更慢。如果您选择使用内联脚本,则有三种选择。

  1. 获取脚本的 SHA-256 哈希值并将其添加到我们的 CSP 中。Chrome 的开发者工具甚至会在控制台显示 CSP 错误时为您生成 SHA-256 哈希值。将其添加到我们当前的 CSP 示例中如下所示:
Content-Security-Policy-Report-Only: default-src 'none'; form-action 'none'; frame-ancestors 'none'; style-src 'self'; script-src 'self' cdnjs.com sha256-c2u0cNUv1GcIb92+ybgJ4yMPatX/k+xxHHbugKVGUU8=; img-src 'self';
Enter fullscreen mode Exit fullscreen mode
  1. 您的服务器会为每个内联脚本生成一个唯一的 nonce。这意味着每个服务器请求都必须生成一个新的 nonce。您可以像 SHA-256 一样将其添加到您的 CSP 中nonce-47c2gtf3a1。您还需要将其添加到脚本标签中:<script nonce="47c2gtf3a1">。由于 nonce 的实现相当不方便,因此很少使用。

  2. 在你的策略中添加允许内联脚本'unsafe-inline',然后羞愧地低下头去。这允许内联脚本,会削弱你的内容安全策略 (CSP) 并允许 XSS 攻击。这样做应该会让你感到难过。

加油!不安全的内联代码不会是世界末日!就你一家。(开个玩笑,算了……)

首次实现内容安全策略 (CSP) 时,很可能需要在 style-src 或 script-src 指令上使用 unsafe-inline。你甚至可能需要使用 unsafe-eval 来允许 JavaScript 的 eval 函数。真是的!

请记住,CSP 应该是您安全武器库中的众多武器之一,而不是唯一的武器。

拥有包含少量不安全规则的 CSP 仍然比完全没有 CSP 要好。完全不实现 CSP 就等于设置所有指令都允许所有不安全的 CSP 规则。

例如,使用 CSS 窃取登录信息的常见方法是向恶意 URL(例如,您在密码登录字段中输入的字母在http://evilexamplesite.com?password=a哪里)发送背景图片或字体的请求a。当您输入密码的下一个字母时,恶意的 CSS 脚本会发送另一个请求,但发送的是该字母而不是a。然后,恶意网站会记录这些请求以确定您的用户名和密码。通过允许我们的 style-src 使用 unsafe-inline,有人可以注入这段恶意代码。幸运的是,他们的代码无法运行,因为我们的 CSP 不允许来自恶意示例网站的 img-src 和 font-src。

你这样做也并非是与坏人为伍。很多网站,包括GitHub和安全专家Troy Hunt 的博客,都使用了 unsafe-inline。Facebook 也使用了 unsafe-eval,甚至要求其部分 SDK 也必须使用它。任何使用 Google Tag Manager 进行分析的人也必须降低其 CSP 安全性。我也必须承认这一点。我的个人博客使用GatsbyJS,在移除 unsafe-inline 之前,有一些问题需要修复。

如果您仍然因为不得不在指令上实施不安全的规则而感到沮丧,可以尝试在网站的每个页面上应用不同的 CSP 标头。如果您有允许或显示来自用户或外部来源的输入的区域,您可以尝试在这些页面上添加更严格的 CSP。

生成 CSP 的其余部分

传统的方法是访问你网站的每个页面,检查这些错误并修复它们。如果你有时间这样做,那就太好了!你甚至可能会喜欢这个很棒的Chrome 扩展程序Fiddler 扩展程序。它们可以让你浏览你的网站,并为你生成合适的内容安全策略 (CSP)。

一年多前,我第一次接触 CSP 时,觉得这项任务对我来说太难完成了。直到那时,我才了解到report-uriCSP 的功能。你可以在 CSP 末尾添加report-uri一个 URL,用于发送报告。浏览器会将任何违反 CSP 的行为发送到你指定的 URL。现在,你的访客只需使用你的网站,就能为你完成所有工作。

以下是浏览器发送的错误示例:

{
    "csp-report": {
        "document-uri": "https://mattferderer.com/",
        "referrer": "",
        "violated-directive": "script-src",
        "effective-directive": "script-src",
        "original-policy": "default-src 'none'; form-action 'none'; frame-ancestors 'none'; report-uri https://mattferderer.report-uri.com/r/d/csp/wizard",
        "disposition": "report",
        "blocked-uri": "inline",
        "line-number": 4,
        "source-file": "https://mattferderer.com/",
        "status-code": 0,
        "script-sample": ""
    }
}
Enter fullscreen mode Exit fullscreen mode

该报告会让您了解发生了什么事以及在哪里发生。

如果您已经有错误日志服务,可以使用它。如果您正在寻找一种免费且简单的入门方法,我推荐使用Report URI

Tala Security的优秀员工运营着类似的服务,他们不久前向我指出,CSP 并非一个设置好就忘掉的工具。随着您的网站或您所依赖的服务更新,您的 CSP 可能需要进行调整。这使得报告服务更具价值。

拥有报告服务还将向您显示运行不同浏览器、浏览器扩展等的用户的真实数据。

我建议您在“仅报告”模式下运行您的 CSP,并将报告发送到服务,直到您确信没有阻止任何有价值的内容发送给用户。完成后,您可以将 CSP 从 更改为Content-Security-Policy-Report-OnlyContent-Security-Policy这将开始强制执行您的 CSP。您仍然可以将 report-uri 保留为 CSP 的一部分,以继续收集错误。

快速入门指南

以下是有关如何开始的简要回顾,其中包含使用报告 URI 的附加说明。

  1. 为您的网站添加严格的 CSP 标头。我建议Content-Security-Policy-Report-Only: default-src 'none'; form-action 'none'; frame-ancestors 'none';

  2. 在Report URI注册一个免费账户请务必验证您的邮箱。否则,服务将无法正常使用。

  3. 使用报告 URI,前往“设置”并创建 CSP 报告地址。将该报告地址添加到您的 CSP:Content-Security-Policy-Report-Only: default-src 'none'; form-action 'none'; frame-ancestors 'none'; report-uri https://yoursite.report-uri.com/r/d/csp/reportOnly

  4. 使用报告 URI,转到 CSP > 我的策略。添加新策略。

  5. 使用“报告 URI”,前往“云服务策略管理 (CSP)”>“向导”。您可以实时监控数据。*您可以在此处为每个指令允许或屏蔽一个网站。这将自动生成您的策略。您可以返回“我的策略”查看。

  6. 使用报告 URI 生成的新策略更新您的 CSP。

  7. 一旦您在仅报告模式下运行了 CSP,并且对报告 URI 中缺少新条目感到满意,请调整您的 CSP,从Content-Security-Policy-Report-OnlyContent-Security-Policy开始强制执行您的 CSP。

*根据您的报告服务,违反 CSP 策略的内联脚本可能不会显示。

附加说明

Twitter 为 Ruby on Rails 开发者提供了一个很棒的软件包,用于设置安全的默认标头。他们还列出了其他流行框架的类似库

GitHub 的 CSP Journey是一篇关于他们在实施 CSP 时遇到的问题的精彩文章。

CSP 快速参考指南和 Scott Helme 的CSP 备忘单是实施 CSP 时值得一看的优秀资源。

如果您需要对特定页面采取额外的预防措施,请查看沙盒模式

最初发布于mattferderer.com

文章来源:https://dev.to/mattferderer/what-is-csp-why--how-to-add-it-to-your-website-28df
PREV
React Drag N' Drop 简介 Showtime 结论
NEXT
微服务通信。为什么应该切换到消息队列。