内容安全策略CSP(Content-Security-Policy)

799 阅读5分钟

概述

内容安全策略(CSP),其核心思想十分简单:网站通过发送一个 CSP 头部,来告诉浏览器什么是被授权执行的与什么是需要被禁止的。其被誉为专门为解决XSS攻击而生的神器。

image.png

前言

内容安全策略 (CSP) 是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本 (XSS) 和数据注入攻击等。无论是数据盗取、网站内容污染还是散发恶意软件,这些攻击都是主要的手段。

CSP 的实质就是白名单制度,开发者明确告诉客户端,哪些外部资源可以加载和执行,等同于提供白名单。它的实现和执行全部由浏览器完成,开发者只需提供配置。

CSP 大大增强了网页的安全性。攻击者即使发现了漏洞,也没法注入脚本,除非还控制了一台列入了白名单的可信主机。


CSP作用

  • 限制资源获取
  • 报告资源获取越权

应对威胁

1 跨站脚本攻击

CSP 的主要目标是减少和报告 XSS 攻击 ,XSS 攻击利用了浏览器对于从服务器所获取的内容的信任。恶意脚本在受害者的浏览器中得以运行,因为浏览器信任其内容来源,即使有的时候这些脚本并非来自于它本该来的地方。

CSP通过指定有效域——即浏览器认可的可执行脚本的有效来源——使服务器管理者有能力减少或消除XSS攻击所依赖的载体。一个CSP兼容的浏览器将会仅执行从白名单域获取到的脚本文件,忽略所有的其他脚本 (包括内联脚本和HTML的事件处理属性)。

作为一种终极防护形式,始终不允许执行脚本的站点可以选择全面禁止脚本执行。

2 数据包嗅探攻击

除限制可以加载内容的域,服务器还可指明哪种协议允许使用;比如 (从理想化的安全角度来说),服务器可指定所有内容必须通过HTTPS加载。一个完整的数据安全传输策略不仅强制使用HTTPS进行数据传输,也为所有的cookie标记安全标识 cookies with the secure flag,并且提供自动的重定向使得HTTP页面导向HTTPS版本。网站也可以使用 Strict-Transport-Security HTTP头部确保连接它的浏览器只使用加密通道。


CSP使用

CSP分类:

  • 限制资源获取:Content-Security-Policy
    配置好并启用后,不符合 CSP 的外部资源就会被阻止加载。

  • 报告资源获取越权:Content-Security-Policy-Report-Only
    表示不执行限制选项,只是记录违反限制的行为。它必须与report-uri选项配合使用。

启用 CSP

  • 通过 HTTP 头信息的Content-Security-Policy的字段(推荐)
// header头配置
Content-Security-Policy: script-src 'self'; object-src 'none';
style-src cdn.example.org third-party.org; child-src https:
`<meta>`标签配置
<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:">

指令说明

以下是常用的指令说明:

指令名demo说明
default-src'self' cdn.example.com默认策略,可以应用于js文件/图片/css/ajax请求等所有访问
script-src'self' js.example.com定义js文件的过滤策略
style-src'self' css.example.com定义css文件的过滤策略
img-src'self' img.example.com定义图片文件的过滤策略
connect-src'self'定义请求连接文件的过滤策略
font-srcfont.example.com定义字体文件的过滤策略
object-src'self'定义页面插件的过滤策略,如 , 或者等元素
media-srcmedia.example.com定义媒体的过滤策略,如 HTML6的 , 等元素
frame-src'self'定义加载子frmae的策略
sandboxallow-forms allow-scripts沙盒模式,会阻止页面弹窗/js执行等,你可以通过添加allow-forms allow-same-origin allow-scripts allow-popups, allow-modals, allow-orientation-lock, allow-pointer-lock, allow-presentation, allow-popups-to-escape-sandbox, and allow-top-navigation 策略来放开相应的操作

指令值

所有以-src结尾的指令都可以用一下的值来定义过滤规则,多个规则之间可以用空格来隔开

demo说明
*img-src *允许任意地址的url,但是不包括 blob: filesystem: schemes.
'none'object-src 'none'所有地址的咨询都不允许加载
'self'script-src 'self'同源策略,即允许同域名同端口下,同协议下的请求
data:img-src 'self' data:允许通过data来请求咨询 (比如用Base64 编码过的图片).
domain.example.comimg-src domain.example.com允许特性的域名请求资源
*.example.comimg-src *.example.com允许从 example.com下的任意子域名加载资源
cdn.comimg-src cdn.com仅仅允许通过https协议来从指定域名下加载资源
https:img-src https:只允许通过https协议加载资源
'unsafe-inline'script-src 'unsafe-inline'允许行内代码执行
'unsafe-eval'script-src 'unsafe-eval'允许不安全的动态代码执行,比如 JavaScript的 eval()方法

验证

可以通过检查headers信息中的Content-Security-Policy字段

image.png


浏览器拦截现象

启用后,不符合 CSP 的外部资源就会被阻止加载。

  • Chrome 的报错信息

image.png

  • Firefox 的报错信息

image.png


配置示例

示例:禁用不安全的内联/动态执行,只允许通过 https 加载这些资源(如图片、字体、脚本等):

// header
Content-Security-Policy: default-src https:

// meta tag
<meta http-equiv="Content-Security-Policy" content="default-src https:">

示例:已经存在的一个网站,用了太多内联代码修复问题,而且想确保资源只从 https 加载,并且禁止插件:

Content-Security-Policy: default-src https: 'unsafe-eval' 'unsafe-inline'; object-src 'none'

注:具体配置需要结合项目情况配合上述指令说明进行配置

如:我使用的是Lighttpd服务器,用了很多内联代码,需要确保资源只从https加载,禁止插件,同时使用了websocket,可以进行一下配置

    setenv.add-response-header += ( "Content-Security-Policy" => "default-src https: 'unsafe-inline'; object-src 'none';connect-src https: wss:")

最后附上其他服务推荐配置以及参考

  • apache

Header set Content-Security-Policy "script-src 'self'; object-src 'self'"

  • nginx

add_header Content-Security-Policy "script-src 'self'; object-src 'self'";