使用浏览器的CSP机制从根本上解决XSS问题

xss
csp

#1

使用浏览器的CSP机制从根本上解决XSS问题

关于 xss 的介绍,和危害。这里不多赘述。自行百度。

什么是CSP机制

网页安全政策(Content Security Policy),实质上就是通过一个HttpHeader来提供一个白名单,让浏览器仅仅可以加载指定的js文件。以及约束内联js的执行。来彻底的杜绝XSS攻击。

Content-Security-Policy

一个简单的案例开始

image

Content-Security-Policy: script-src 'none';img-src 'self' https://baidu.com;
  • script-src 表示一个选项,该选项的主要作用就是指定 js代码的加载白名单。它的值目前是 none 表示不从任何URL加载 js 脚本。如果 html 有执行加载的话,浏览器会抛出异常

  • img-src 选项表示限制 html 页面中的图片加载地址。它有两个值。self 表示允许从当前的域中加载,还允许从 https://baidu.com 下加载。如果加载的图片地址不在白名单内,那么浏览器就会阻止加载,并且给出异常

常用的限制选项

选项 限制内容
script-src 外部脚本
style-src 样式表
img-src 图像
media-src 媒体文件(音频和视频)
font-src 字体文件
object-src 插件,比如 Flash
child-src 框架
frame-ancestors 嵌入的外部资源,比如frame iframe embedapplet
connect-src HTTP 连接(通过 XHRWebSocketsEventSource等)
worker-src worker脚本
manifest-src manifest 文件
default-src 上述所有选项的默认选项(可以被覆盖)

可以有多个选项,每个选项之间使用分号; 分割。如果同一个选项多次声明,只有第一个会生效。

选项值的表达式

限制主机

 http://springboot.io
 https://statis.springboot.io

限制路径

 http://springboot.io/assert/js/

使用通配符限制

*.example.org      //任意协议,指定域名,指定端口(80)
*://*.example.com:* // 任意协议,指定域名,任意子域名,任意端口

限制使用的协议

https:   // 允许以https:协议加载
data:  // 允许以data:协议加载

关键字 self 和 none

关键字必须添加单引号

script-src 'none' //none 表示禁止加载
img-src 'self' // self 表示允许从当前域加载

script-src 选项的特殊值

下列值,都是关键字,在设置的时候,必须使用单引号

unsafe-inline
如果设置了该值,表示允许内嵌的<script> 代码块,和标签上的事件监听函数执行。

unsafe-eval
如果设置了该值,允许将字符串当作代码执行,比如使用 eval setTimeout setIntervalFunction等函数。

nonce
该值表示一个授权值,只有通过该值授权的内联代码块才能执行

Content-Security-Policy: script-src 'nonce-123456'

<script type="text/javascript" nonce="123456">
    console.log('内联代码执行');
</script>

<script> 标签上添加一个 nonce 属性,该属性的值。与 header 中 nonce 的值一样。该内联代码块才能执行。该值的表达式:once-字符串

hash
该值表示内联代码块中js代码的hash值。只有在内联代码块的hash值匹配的时候才能执行

content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='

<script>alert('Hello, world.');</script>

该值的表达式:hash算法名-hash值

report-uri 报告

report-uri 用来设置一个回调,在浏览器发生注入异常的时候,浏览器会把详细的信息提交给该回调地址。

content-Security-Policy: report-uri /xss/report;  // 把注入异常提交到 /xss/report

提交的是一个JSON体

{
	"csp-report": {
		"document-uri": "http://example.org/page.html",	//发生违规的文档的URI。
		"referrer": "http://evil.example.com/",	//referrer
		"blocked-uri": "http://evil.example.com/evil.js",	//被CSP阻止的资源URI。如果被阻止的URI来自不同的源而非文档URI,那么被阻止的资源URI会被删减,仅保留协议,主机和端口号。
		"violated-directive": "script-src 'self' https://apis.google.com", //违反的策略名称。
		"original-policy": "script-src 'self' https://apis.google.com; report-uri http://example.org/my_amazing_csp_report_parser" // 在 Content-Security-Policy HTTP 头部中指明的原始策略。
	}
}

其他一些可以限制的选项

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

upgrade-insecure-requests
自动将网页上所有加载外部资源的 HTTP 链接换成 HTTPS 协议

plugin-types
限制可以使用的插件格式

sandbox
浏览器行为的限制,比如不能有弹出窗口等

参考信息

http://www.ruanyifeng.com/blog/2016/09/csp.html