# 背景

  • 跨站脚本攻击XSS是最常见、危害最大的网页安全漏洞
  • 为了从根本上解决问题,浏览器自动禁止外部注入恶意脚本

# 简介

  • 本质是白名单制度
  • 大大增强了网页的安全性

# 生效方式

  • Http响应头信息的 Content-Security-Policy字段
  • 网页的**标签**

# 配置规则

# 配置项(主要)

配置项名称 作用
script-src 外部脚本
style-src 样式表
img-src 图像
media-src 媒体文件(音频和视频)
font-src 字体文件
object-src 插件(如 Flash)
child-src 框架
frame-ancestors 可被嵌入的外部网页(如frame,iframe,embed,applet)
connect-src http连接(如XHR,WebSocket等)

# 默认配置项

  • default-src,用于配置内容安全策略各选项的默认值.
  • 同时配置了单项限制,将会覆盖默认值

# 其它限制

  • block-all-mixed-content: Https网页不得加载http资源(浏览器已经默认开启)

# 配置项的值类型

值类型 值示例
主机名 example.org,https://example.com:443
路径名 example.org/resources/js
通配符 *.example.org, *😕/*.example.com:*(表任意协议,任意子域名,任意端口)
协议名 https:,data:
关键字'self' ’selft‘, 当前域名,需要加引号
关键字'none' 'none', 禁止加载任何外部资源,需要加引号
  • 多个值可以并列,用空格分隔
  • 同一个限制选项使用多次,只有第一次会生效,如script-src https://host1.com; script-src https://host2.com,host1生效

# script-src的特殊值

特殊值 特殊值含义
'unsafe-inline' 允许执行页面内嵌的<script>标签和事件监听函数
’unsafe-eval‘ 允许将字符串当作代码执行,如使用eval,setTimeout,setInterval和Function等
nonce值 每次http响应给出一个授权token,页面内嵌脚本必须有这个token,才会执行
hash值 流出允许执行的脚本代码的hash值,页面内嵌脚本的hash值,只有温和的情况下,才能执行

# 注意事项

  • script-src和 object-src是必设的,除非设置了 default-src
  • script-src不建议使用unsafe-inline关键字(除非伴随一个nonce值),也不建议设置 data:;
    <img src="x" onerror="evil()">
    <script src="data:text/javascript,evil()"></script>
    

# 兼容性

  • 在老版本浏览器不支持 CSP之前,可支持X-Frame-Option 增加安全性
  • 支持 CSP的浏览器,则不再支持 X-Frame-Option

# 实践

  • 配置放行类似于 “黑名单规则”,即不限制即放行;

# 实例说明

<filter>
        <filter-name>FrontEndResourceCSPFilter</filter-name>
        <filter-class>xxx.xxx.xxx.common.FrontEndResourceCSPFilter</filter-class>
        <init-param>
            <param-name>cspPolicy</param-name>
            <param-value>default-src 'self' 'unsafe-inline' 'unsafe-eval' 'self' 172.20.20.52:* 172.20.20.119:* *.baidu.com wss: data: ws: ; frame-ancestors 'self';</param-value>
        </init-param>
 </filter>
  • 该例允许 所有的 ws协议,data协议,wss协议连接(未指定具体地址); 允许主机 172.20.20.52, 172.20.20.19的所有连接(未指定协议及端口,此处协议特指http以及https), 允许域名baidu.com及其子域名的所有连接(通配);
  • 如果不限制端口,需要使用通配进行指定(https默认443端口,http默认80端口);
  • http或者https协议,不需要使用通配进行指定;