- A+
本文是与地面...感谢您支持使SitePoint成为可能的合作伙伴。
网络是基于“同一来源”的政策。只有代码在mysite.com可以在cookie、localStorage、Ajax请求等中访问mysite.com的数据。evilsite.com将被拒绝。
不幸的是,事情从来没有那么简单。现代网站是复杂的,并加载了各种第三方组件,风格和脚本.从另一个域加载的脚本在当前页面的上下文中运行,可以执行它喜欢的任何操作。社交网络按钮可以监视访问者,劫持登录cookie,更改页面内容等等。即使您信任第三方站点,您也可能成为中间人攻击在脚本到达您之前进行更改的位置。或者,它可以允许用户启动自己的跨站点脚本攻击(XXS).
默认情况下,浏览器实现任何事-去接近。幸运的是,可以使用防止意外安全问题的内容安全策略(ContentSecurityPolicy,CSP)应用限制。CSP告诉浏览器什么是允许的,例如在mysite.com上运行JavaScript,但只能从文件中运行,而不是内联的
1 | <script> |
标签。
测试你的网站
若要检查csp是否在您的站点上实现,请访问observatory.mozilla.org,输入页面URL并按下扫描我...那些没有CSP保护的人很可能F(虽然进行了其他各种检查)。
CSP对于银行、在线商店、社交网络和任何实现用户帐户的网站来说都是必不可少的。如果您的站点不使用第三方脚本、字体、媒体、小部件或分析工具,这就不那么必要了,但您能确定它永远不会使用吗?
实现内容安全策略
开发人员或Web主机必须向每个页面添加内容安全策略。它使用内容-安全-策略由服务器端语言设置的http头(PHP、Node.js、Ruby等)或在服务器配置(如Apache的
1 | .htaccess |
文件,例如:
1
2
3
4 # Apply a CSP to all HTML and PHP files
<FilesMatch ".(html|php)$">
Header set Content-Security-Policy "policy-definition"
</FilesMatch>
(我们将很快讨论“策略定义”值。)
服务器配置文件是实用的,因为它们将相同的头应用于子文件夹层次结构中的所有页面。但是,您也可以在HTML中定义策略
1 | <head> |
使用
1 | meta |
标签:
1 <meta http-equiv="Content-Security-Policy" content="policy-definition">
如果您没有配置服务器的权限,或者在每个页面上需要不同的策略,这可能是必要的。
内容安全策略定义
现在是复杂的部分。CSP为不同类型的内容定义了允许域和上下文的白名单。
假设您只希望允许从您的域加载脚本。您可以使用以下CSP(请不要真的这么做--这只是个例子!):
1 script-src 'self';
然后,您会意识到,您还将从cdn加载一个第三方库,该库可以出现在
1 | mycdn.com |
...域通配符添加到空格分隔列表中:
1 script-src 'self' *.mycdn.com;
然后,您会记住一些在页面上内联运行的脚本--我们也可以定义:
1 script-src 'self' *.mycdn.com 'unsafe-inline';
我们现在有了脚本策略。但是,我们还没有定义其他类型,所以所有样式表、图像、字体等等都无法加载。要解决这个问题,我们可以使用
1 | default-src |
作为任何未定义类型的后盾:
1 default-src 'self'; script-src 'self' *.mycdn.com 'unsafe-inline';
注意,每个内容类型定义都用分号(;)分隔。我们现在可以在我们的
1 | .htaccess |
档案:
1 Header set Content-Security-Policy "default-src 'self'; script-src 'self' *.mycdn.com 'unsafe-inline';"
或者页面元标签:
1
2 <meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' *.mycdn.com 'unsafe-inline';">
CSP指令参考
整套CSP指令:
指令 | 描述 | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
默认的后备策略。通常设置为
或
为了确保所有其他指令都必须声明 |
||||||||||||||||||||||||
|
有效样式表源 | ||||||||||||||||||||||||
|
有效JavaScript源 | ||||||||||||||||||||||||
|
用于JavaScript数据检索的有效Ajax、WebSocket或事件源源 | ||||||||||||||||||||||||
|
有效来源
动作属性 |
||||||||||||||||||||||||
|
有效图像源 | ||||||||||||||||||||||||
|
有效字体源 | ||||||||||||||||||||||||
|
有效HTML 5
和
元素源 |
||||||||||||||||||||||||
|
HTML的有效插件源
,
和
元素 |
||||||||||||||||||||||||
|
调用的插件的有效MIME类型。
和
,G.
|
||||||||||||||||||||||||
|
有效
和
来源(现在已被废弃-使用)
) |
||||||||||||||||||||||||
|
有效
和
来源 |
||||||||||||||||||||||||
|
有效嵌入源
,
,
,
和
元素 |
||||||||||||||||||||||||
|
以类似于HTML 5
沙箱属性...这有一些限制是本指令所特有的:
,
,
,
,
,
,
,
,
,和
|
||||||||||||||||||||||||
|
浏览器可以发布策略失败报告的地址。 |
CSP源参考
终止的CSP源指令
1 | -src |
支持下列值。可以使用任意数量的空格分隔值:
来源 | 描述 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
防止从任何源加载,例如:
停止显示任何iframe或插件的页面。该值不能跟随其他源。 |
||||||||
|
允许从同一来源的源(协议、域/ip和端口)加载 | ||||||||
|
只允许HTTPS连接上的源。 | ||||||||
|
许可证数据:来源,例如
允许样式表中使用Base 64编码的图像。 |
||||||||
|
任何URL的通配符 | ||||||||
|
允许来自domain.com的任何子域的来源,即www.domain.com、cdn.domain.com等。 | ||||||||
|
许可来源:eart.domain.com | ||||||||
|
允许在给定域上使用https源。 | ||||||||
|
允许内联CSS、脚本、
和元素事件处理程序(如
在HTML中 |
||||||||
|
允许使用JavaScript的不安全动态代码
功能 |
||||||||
|
允许内联CSS或脚本运行,如果
匹配当前属性值,例如
在
块 |
||||||||
|
如果文件内容与生成的sha-256散列值匹配,则允许样式或脚本。 |
CSP发展建议
从严格的默认策略开始是切实可行的
1 | default-src 'none'; |
然后根据需要添加进一步的权限。对大多数网站来说,一个很好的起点可以是:
1 default-src 'none'; style-src 'self' data:; img-src 'self' data:; script-src 'self'; connect-src 'self';
这允许相同来源的样式、图像、脚本和Ajax请求。
在Web浏览器中打开页面,然后启动Developer工具控制台。将报告阻塞的资源警告。
1 Refused to load the script 'XXX' because it violates the following Content Security Policy directive: "YYY".
您可能需要浏览各种页面,以确保您已经考虑到所有的字体,图像,视频,脚本,插件和IFRAME您的网站所需。
谷歌服务
Google提供了范围广泛的服务,您可能正在使用分析、字体、地图等等。不幸的是,在一系列URI上启用了这些功能,这些URI需要进一步的Ajax调用、内联执行和数据方案。您可能最终会得到一个复杂的策略,例如:
1
2
3
4
5
6 default-src 'self';
style-src 'self' 'unsafe-inline' *.googleapis.com;
script-src 'self' *.google-analytics.com *.googleapis.com data:;
connect-src 'self' *.google-analytics.com *.googleapis.com *.gstatic.com data:;
font-src 'self' *.gstatic.com data:;
img-src * data:;
(为了清晰起见,添加了行符,但不能在实际代码中使用。)
在编写本报告时,这是无法避免的,其他第三方供应商也将面临类似的挑战。