内容安全策略 (CSP) 如何工作?

我在开发人员控制台中收到一堆错误:

拒绝计算字符串

拒绝执行内联脚本,因为它违反了以下内容安全策略指令

拒绝加载脚本

拒绝加载样式表

这到底是怎么回事?内容安全策略 (CSP) 如何工作?如何使用 HTTP 标头?Content-Security-Policy

具体来说,如何...

  1. ...是否允许多个来源?
  2. ...使用不同的指令?
  3. ...使用多个指令?
  4. ...处理端口?
  5. ...处理不同的协议?
  6. ...允许协议?file://
  7. ...使用内联样式、脚本和标记以及 ?<style><script>
  8. ...允许?eval()

最后:

  1. 这到底是什么意思?'self'

答案 1

元标记允许您定义从哪里加载资源,从而防止浏览器从任何其他位置加载数据,从而降低 XSS 攻击的风险。这使得攻击者更难将恶意代码注入您的网站。Content-Security-Policy

我把头撞在砖墙上,试图弄清楚为什么我一个接一个地出现CSP错误,而且似乎没有任何关于它如何工作的简洁,清晰的说明。因此,我试图简要解释CSP的一些要点,主要集中在我发现难以解决的问题上。

为简洁起见,我不会在每个示例中写入完整的标记。相反,我将只显示属性,因此示例表示:contentcontent="default-src 'self'"

<meta http-equiv="Content-Security-Policy" content="default-src 'self'">

1. 如何允许多个来源?

您只需在指令之后以空格分隔的列表形式列出源:

content="default-src 'self' https://example.com/js/"

请注意,除了特殊参数(如 .此外,指令后面没有冒号 ()。只是指令,然后是空格分隔的参数列表。'self':

隐式允许指定参数以下的所有内容。这意味着在上面的示例中,这些是有效的源:

https://example.com/js/file.js
https://example.com/js/subdir/anotherfile.js

但是,这些无效:

http://example.com/js/file.js
^^^^ wrong protocol

https://example.com/file.js
                   ^^ above the specified path

2. 如何使用不同的指令?他们每个人都是做什么的?

最常见的指令是:

  • default-src加载javascript,图像,CSS,字体,AJAX请求等的默认策略
  • script-src定义了 javascript 文件的有效源
  • style-src定义 css 文件的有效源
  • img-src定义图像的有效源
  • connect-src定义了 XMLHttpRequest (AJAX)、WebSockets 或 EventSource 的有效目标。如果尝试连接到此处不允许的主机,则浏览器将模拟错误400

还有其他的,但这些是你最有可能需要的。

3. 如何使用多个指令?

您可以通过用分号 () 终止所有指令来定义一个元标记中的所有指令:;

content="default-src 'self' https://example.com/js/; style-src 'self'"

4. 如何处理端口?

除默认端口之外的所有内容都需要通过在允许的域后添加端口号或星号来显式允许:

content="default-src 'self' https://ajax.googleapis.com http://example.com:123/free/stuff/"

以上将导致:

https://ajax.googleapis.com:123
                           ^^^^ Not ok, wrong port

https://ajax.googleapis.com - OK

http://example.com/free/stuff/file.js
                 ^^ Not ok, only the port 123 is allowed

http://example.com:123/free/stuff/file.js - OK

正如我所提到的,您还可以使用星号显式允许所有端口:

content="default-src example.com:*"

5. 如何处理不同的协议?

默认情况下,只允许使用标准协议。例如,要允许WebSockets,您必须明确允许它:ws://

content="default-src 'self'; connect-src ws:; style-src 'self'"
                                         ^^^ web Sockets are now allowed on all domains and ports.

6. 如何允许文件协议 file://

如果您尝试将其定义为这样,它将不起作用。相反,您将使用参数允许它:filesystem

content="default-src filesystem"

7. 如何使用内联脚本和样式定义?

除非明确允许,否则不能使用内联样式定义、标记内的代码或标记属性(如 .你允许他们这样:<script>onclick

content="script-src 'unsafe-inline'; style-src 'unsafe-inline'"

您还必须明确允许内联的 base64 编码图像:

content="img-src data:"

8. 如何允许 eval()

我相信很多人会说你没有,因为“eval是邪恶的”,这是世界末日即将到来的最有可能的原因。那些人会错的。当然,您绝对可以通过eval在网站的安全性上打入重大漏洞,但它具有完全有效的用例。你只需要聪明地使用它。你允许它,就像这样:

content="script-src 'unsafe-eval'"

9. “自我”到底是什么意思?

您可以表示本地主机,本地文件系统或同一主机上的任何内容。这并不意味着这些中的任何一个。它表示与定义内容策略的文件具有相同的方案(协议)、相同主机和相同端口的源。通过 HTTP 为您的网站提供服务?那么没有https,除非你明确定义它。'self'

我在大多数例子中使用过,因为它通常有意义,但它绝不是强制性的。如果您不需要它,请将其排除在外。'self'

但是等一下!我不能只是使用并完成它吗?content="default-src *"

不。除了明显的安全漏洞之外,这也不会像您预期的那样工作。尽管有些文档声称它允许任何东西,但事实并非如此。它不允许内联或评估,所以要真正,真正使您的网站特别容易受到攻击,您将使用以下内容:

content="default-src * 'unsafe-inline' 'unsafe-eval'"

...但我相信你不会。

延伸阅读:

http://content-security-policy.com

http://en.wikipedia.org/wiki/Content_Security_Policy


答案 2

阿帕奇 2 mod_headers

您也可以mod_headers启用 Apache 2。在 Fedora 上,它已默认启用。如果你使用 Ubuntu/Debian,请像这样启用它:

# First enable headers module for Apache 2,
# and then restart the Apache2 service
a2enmod headers
apache2 -k graceful

在 Ubuntu/Debian 上,您可以在文件中配置头文件/etc/apache2/conf-enabled/security.conf

#
# Setting this header will prevent MSIE from interpreting files as something
# else than declared by the content type in the HTTP headers.
# Requires mod_headers to be enabled.
#
#Header set X-Content-Type-Options: "nosniff"

#
# Setting this header will prevent other sites from embedding pages from this
# site as frames. This defends against clickjacking attacks.
# Requires mod_headers to be enabled.
#
Header always set X-Frame-Options: "sameorigin"
Header always set X-Content-Type-Options nosniff
Header always set X-XSS-Protection "1; mode=block"
Header always set X-Permitted-Cross-Domain-Policies "master-only"
Header always set Cache-Control "no-cache, no-store, must-revalidate"
Header always set Pragma "no-cache"
Header always set Expires "-1"
Header always set Content-Security-Policy: "default-src 'none';"
Header always set Content-Security-Policy: "script-src 'self' www.google-analytics.com adserver.example.com www.example.com;"
Header always set Content-Security-Policy: "style-src 'self' www.example.com;"

注意:这是文件的底部。只有最后三个条目是 CSP 设置。

第一个参数是指令,第二个是要列入白名单的源。我已经添加了Google分析和广告服务器,您可能拥有这些内容。此外,我发现如果你有别名,例如,www.example.com 和在Apache 2中配置 example.com,你也应该将它们添加到白名单中。

内联代码被认为是有害的,您应该避免它。将所有 JavaScript 代码和 CSS 复制到单独的文件中,并将其添加到白名单中。

当您使用它时,您可以查看其他标头设置并安装mod_security

延伸阅读:

https://developers.google.com/web/fundamentals/security/csp/

https://www.w3.org/TR/CSP/