内容安全政策如何运作?

我在开发者控制台中遇到了一堆错误:

拒绝评估一个string

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

拒绝加载脚本

拒绝加载样式表

这是关于什么的? 内容安全政策如何运作? 如何使用Content-Security-Policy HTTP标头?

具体来说,如何…

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

最后:

  1. 'self'究竟是什么意思?

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

我试图弄清楚为什么我会一个接一个地看到CSP错误,而且似乎没有关于它是如何工作的简明明了的指示。 所以我试图简单地解释CSP的一些观点,主要集中在我发现很难解决的事情上。

为了简洁起见,我不会在每个样本中写完整的标签。 相反,我只会显示content属性,所以说content="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'" ^^^ websockets 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. 'self'究竟是什么意思?

你可以把'self'表示本地主机,本地文件系统或者同一主机上的任何东西。 这并不意味着任何这些。 这意味着与内容策略定义的文件具有相同的scheme(协议),相同的主机和相同的端口的来源。通过http服务您的网站? 除非你明确地定义它,否则没有https。

在大多数例子中,我使用了'self' ,因为通常包含它是有意义的,但这并不是强制性的。 如果你不需要,就把它留下。

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

没有。除了明显的安全漏洞之外,这样做也不会像预期的那样工作。 即使有些文件声称它允许任何事情,这是不正确的。 它不允许内联或evals,所以要真正让你的网站变得更加脆弱,你可以使用这个:

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

…但是我相信你不会。

进一步阅读:

http://content-security-policy.com

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

APACHE2 MOD_HEADERS

你也可以启用Apache2的mod_headers,在Fedora上它已经默认启用了,如果你使用Ubuntu / Debian启用它就像这样:

 # First enable headers module for Apache2, # 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;" 

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

第一个参数是指令,第二个是白名单的来源。 我已经添加了Google Analytics(分析)和一个广告服务器,您可能已经有了。 此外,我发现如果你有别名,例如www.example.com和example.comconfiguration在Apache2中,你也应该把它们添加到白名单中。

内联代码被认为是有害的,你应该避免它。 复制所有的JavaScript和CSS来分开文件,并将它们添加到白名单。

当你在这里,你可以看看其他的头文件设置,并安装mod_security

进一步阅读:

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

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