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

How does Content Security Policy (CSP) work?

本文关键字:何工作 工作 CSP 安全策略      更新时间:2023-09-26

我在开发者控制台得到一堆错误:

拒绝计算字符串

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

拒绝加载脚本

拒绝加载样式表

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

具体来说,是如何……

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

最后:

  • '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'"
                                             ^^^ 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'表示本地主机、本地文件系统或同一主机上的任何东西。它并不是指这些。它是指与定义内容策略的文件具有相同的方案(协议)、相同的主机和相同的端口的源。通过HTTP服务您的站点?没有https,除非你明确定义。

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

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

    。除了明显的安全漏洞之外,这也不会像您期望的那样工作。尽管一些医生声称它允许任何事情,但事实并非如此。它不允许内联或求值,所以为了让你的网站更容易受到攻击,你可以这样写:

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

    …但我相信你不会。

    进一步阅读:

    http://content-security-policy.com

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

    Apache 2 mod_headers

    你也可以启用Apache 2的mod_headers。在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设置。

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

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

    当你在它你可以看看其他头设置和安装mod_security

    进一步阅读:

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

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