首页 文章

内容安全策略如何运作?

提问于
浏览
187

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

拒绝评估拒绝执行内联脚本的字符串,因为它违反了以下内容安全策略指令拒绝加载脚本拒绝加载样式表

这是怎么回事?内容安全策略如何运作?如何使用 Content-Security-Policy HTTP标头?

具体来说,如何......

  • ...允许多个来源?

  • ...使用不同的指令?

  • ...使用多个指令?

  • ...处理端口?

  • ...处理不同的协议?

  • ...允许 file:// 协议?

  • ...使用内联样式,脚本和标签 <style><script>

  • ...允许 eval()

最后:

  • 'self' 究竟是什么意思?

2 回答

  • 12

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

    我撞到了一堵砖墙,试图弄清楚为什么我一个接一个地得到CSP错误,并且我没有简单地解释CSP的点数,主要集中在我发现很难解决的问题上 .

    为简洁起见,我不会在每个样本中写出完整的标签 . 相反,我只会显示 content 属性,所以一个说 content="default-src 'self'" 的样本意味着:

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

    1. How to allow multiple sources?

    您可以在指令之后将源列出为空格分隔列表:

    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. How to use different directives, what do they each do?

    最常见的指令是:

    • default-src 加载javascript,图像,CSS,字体,AJAX请求等的默认策略

    • script-src 定义了javascript文件的有效来源

    • style-src 定义了css文件的有效源

    • img-src 定义图像的有效来源

    • connect-src 定义了XMLHttpRequest(AJAX),WebSockets或EventSource的有效目标 . 如果尝试连接到此处不允许的主机,浏览器将模拟 400 错误

    还有其他人,但这些是你最需要的 .

    3. How to use multiple directives?

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

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

    4. How to handle ports?

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

    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. How to handle different protocols?

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

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

    6. How to allow the file protocol file://?

    如果你'll try to define it as such it won’t work. Instead, you' ll允许它与 filesystem 参数:

    content="default-src filesystem"
    

    7. How to use inline scripts and style definitions?

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

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

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

    content="img-src data:"
    

    8. How to allow eval()?

    我相信很多人会说你没有,因为'评估是邪恶的',并且最有可能导致世界即将结束 . 那些人会错的 . 当然,你可以使用eval将主要漏洞打入你网站的安全性,但它具有完全有效的用例 . 你只需要聪明地使用它 . 你允许这样:

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

    9. What exactly does 'self' mean?

    您可以将 'self' 表示为localhost,本地文件系统或同一主机上的任何内容 . 它并不意味着任何这些 . 它意味着具有与定义内容策略的文件相同的方案(协议),相同主机和相同端口的源 . 通过HTTP服务您的站点?除非您明确定义,否则暂无https .

    我在大多数例子中使用了 'self' ,因为包含它通常是有意义的,但是它需要它 .

    But hang on a minute! 我不能只使用 content="default-src *" 并完成它吗?

    不会 . 除了明显的安全漏洞之外,这也会让它无法正常工作正如你所期望的那样 . 虽然some docs声称它允许任何内容,但是's not true. It doesn'允许内联或逐渐攻击,所以真的,真的,让你的网站更加脆弱,你会使用这个:

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

    ......但我相信你不会 .

    Further reading:

    http://content-security-policy.com

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

  • 439

    APACHE2 MOD_HEADERS

    您也可以在Fedora上启用Apache2 mod_headers,默认情况下已启用它,如果您使用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分析和广告服务器 . 此外,我发现如果您有别名,例如,在Apache2中配置了www.example.com和example.com,您也应该将它们添加到白名单中 .

    内联代码被认为是有害的,你应该避免它 . 将所有javascripts和css复制到单独的文件中,并将它们添加到白名单中 .

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

    Further reading:

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

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

相关问题