如何实施内容安全策略?

11
有很好的文章解释了CSP的选项,比如这篇文章:http://www.html5rocks.com/en/tutorials/security/content-security-policy/ 也许这很显然,因为我找不到任何好的例子,但是你实际上如何在实践中实现CSP呢?
在PHP中,您可以设置要提供的页面的标头,但是如果您只有一个HTML文件怎么办?您必须通过您的Web服务器(如Apache)来执行吗?这似乎不是一种简单的方法。
在这里的最佳实践是什么?每个单独提供的页面都应该手动设置标头吗?
谢谢!
3个回答

8

最终选择权在你手中。 如果你在Apache Web服务器中全局设置它,那么它将适用于每个页面。 如果需要更精细的方法,你也可以在单个页面上设置头信息。

查看这些网站以获取帮助构建CSP规则:

https://csp-evaluator.withgoogle.com/

https://report-uri.io/home/generate

Scott Helme对这个主题了解很多,并且还有一些不错的例子。 你也可以将报告发送到他的网站进行一些基本分析。

https://scotthelme.co.uk/content-security-policy-an-introduction/

这也可能对Apache配置感兴趣。 使用Apache 2.4生成nonce(用于内容安全策略标头) 我还强烈建议您阅读本文,其中讨论了一些更新的(看起来更简单)配置方法和浏览器向后兼容性。

https://www.websec.be/blog/cspstrictdynamic/

这是一篇来自谷歌研究的优秀论文"CSP已死,长命CSP!",特别是第4节"改进CSP",通过绕过白名单和传播信任。

https://research.google.com/pubs/pub45542.html

多读一些相关内容,当你准备好实施时,使用“REPORT ONLY”模式指令,这样你就可以在不执行策略强制执行的情况下获得控制台消息。

Content-Security-Policy-Report-Only: <policy-directive>; <policy-directive>

一旦你满意了,就可以执行规则:

Content-Security-Policy: <policy-directive>; <policy-directive>

在此基础上,我还遇到了两个调试问题,当我在Apache服务器上实现时。1.尽管json.org/json-en.html说JSON中不允许使用单引号,但在实现Report-To标头时,我能够(并且只能使用)单引号(转义双引号无效):Header always set Report-To "{'group': 'csp-endpoint', 'max_age': 10886400, 'url': '/csp-violation-report-endpoint.php'}"。2.客户端广告拦截器可能会阻止POST报告CSP违规行为。当我测试我的解决方案时,我遇到了uBlock的问题,但禁用uBlock可以正常工作。希望对你有所帮助! - WOUNDEDStevenJones

3
如果您正在运行Apache,则可以使用.htaccess来完成此操作。在您的项目路径中放置一个名为.htaccess的文件(通常类似于/var/www/myProject),如果由于其他原因不存在,则添加以下标题规则:
Header set Content-Security-Policy "
    default-src 'self';
    script-src 'self' www.google-apis.com *.cloudflare.com someotherDomain.com;
    img-src 'self' *.cloudflare.com;
"

现代浏览器仅会执行来自您的域名、google-apis.com、cloudflare.com或someotherDomain.com的脚本。 图像只能从您的域名和cloudflare加载。 其它所有内容只允许来自您的域名。
非常好的参考来源: ole.michelsen.dk

3
“这似乎不是一个简单的方法。”
“是的,确实不容易。但是有一些聪明的捷径可以采取。”
“那么你如何实际实现CSP呢?在PHP中,您可以在提供的页面上设置标头,但是如果您只有一个HTML文件怎么办?您必须通过Web服务器(例如Apache)来执行吗?这似乎不是一个简单的方法。”
“我编写了一个命令行PHP脚本,它接受一个JSON块(类似于代码块A),组装一个类似于代码块B的字符串,并将其保存到一个单独的文件中。”
{
    "script-src": [ "self",  "https://apis.google.com" ]
}

B:

add_header Content-Security-Policy "script-src: 'self' https://apis.google.com";

然后我添加了一行配置,为该虚拟主机配置我的nginx配置文件,以包含生成的CSP指令:

include /path/to/script/output.conf;

由于这个系统的存在,如果我想要修改CSP头文件,只需要编辑一个JSON文件即可。
这就是我如何让CSP头文件易于管理。不同情况可能会有所不同。
这是链接:CSP Builder

谢谢你的回答。那么,使用这个设置,所有页面都会有相同的CSP设置吗?这将是一个限制,我想这是一种权衡。 - Richard
我不会说这是一种限制。你可以轻松地选择退出为特定的虚拟主机设置,并在每个页面上设置它,但要注意,如果您想添加自己的标头,则必须通过PHP脚本处理所有资源。 - Scott Arciszewski
如果我将这段代码添加到我的PHP脚本中,浏览器将无法再加载任何必需品:header("Content-Security-Policy: default-src 'self';script-src 'self'"); - rubo77

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接