小编典典

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

all

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

拒绝评估字符串

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

拒绝加载脚本

拒绝加载样式表

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

具体如何…

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

最后:

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

阅读 63

收藏
2022-04-13

共1个答案

小编典典

元标记允许您定义可以从何处加载资源,防止浏览器从任何其他位置加载数据,从而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'"
                                         ^^^ 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. 究竟是什么'self'意思?

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

'self'在大多数示例中都使用过,因为包含它通常是有意义的,但这绝不是强制性的。如果您不需要它,请不要使用它。

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

不会。除了明显的安全漏洞之外,这也不会像您期望的那样工作。尽管有些文档声称它允许任何事情,但事实并非如此。它不允许内联或评估,因此要真正让您的网站更加脆弱,您可以使用:

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

…但我相信你赢了。

2022-04-13