安全 – CSP (Content Security Policy)
前言
之前讲过 CSRF。防 Cookie hacking 的。
也介绍过防 XSS 的 HtmlSanitizer。
今天再介绍 CSP。
参考
CSP (Content Security Policy) 介绍
它是游览器其中一种防 hack 机制。除 IE 以外,modern browser 老早就全部支持了,所以可以安心用。
它主要是防 html 里要加载的 resource。
比如 HTML 想加载 JavaScript, Image 等等。
首先游览器会去检查 CSP config,然后验证这些 resource 是否符合 config 要求,如果 ok 才加载,不 ok 就报错,不加载。
此外它还可以防 inline JavaScript 的执行,还有网页被 ifame 嵌套等等。算是满全面的防 hack 机制。
Config CSP
same origin resource
CSP 可以设置在 header,也可以放到 HTML 的 meta 里。
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
这是一个用 meta 定义 CSP 的例子。所有的 config 都会写到 content 里。分隔符是空格和分号。
用 header 的话,key 是 Content-Security-Policy,value 是 default-src 'self'。
CSP 可以配置不同 src 的条件,比如 script-src 指的是 JavaScript,img-src 指的是图片,而 default-src 指的是所有 src 默认的条件。
上面这句 default-src 'self' 意思是 HTML 里所有要加载的 resource 必须来自于 self / 同域 / same-origin。
<script src="/script.js"></script>
<script src="https://192.168.1.152:44300/script.js"></script>
假设我的 origin 是 http://localhost:5148,上面 /script.js 可以加载,但是 https://192.168.1.152:44300/script.js 就不行,因为它不是 same origin。
运行的结果就是游览器会报错。

wss: 和 https:
除了 https://192.168.1.152:44300/script.js,还有一个 resource 也被拒绝了 wss://localhost:61341,这个是 ASP.NET Core development mode 情况下开启的 websocket,作用是自动刷新 browser。
如果我们想 allow 它,可以这样配置。
<meta http-equiv="Content-Security-Policy" content="default-src 'self' wss:">
加了一个 wss:,我没有声明完整的 origin,只声明了 protocol,所有只要是 websocket 请求,不管什么 origin 都被允许。类似的设置还有 https: 表示只要是 https 安全请求就允许。
inline script
'self' 并不能 bypass inline script。
<script>alert('inline script');</script>
CSP 防御下,inline script 会报错。

unsafe-inline
<meta http-equiv="Content-Security-Policy" content="default-src 'self' wss: 'unsafe-inline'">
添加 unsafe-inline 就可以 bypass inline script 了,但是这个方法是相对不安全的操作,除非我们可以完全信赖 inline script。
更安全的 by pass 方式是通过 sha256。我们把 inline script 拿去 sha256 + base64 得到 hash。
然后这样配置 CSP
<meta http-equiv="Content-Security-Policy" content="default-src 'self' wss: 'sha256-HgfVE1WaRXdD1n+LcUazTiP/FMatVgqvpPh9iAxr2qE='">
只要 inline script 的内容 sha256 后和 CSP 匹配,那么游览器才允许执行代码。
要得到这个 sha256 有很多种方式
2. Chrome 报错的时候会提供 sha256 的 hash,参考上面的 error。
3. 通过 C#
var script = "alert('inline script');";
var sha256Script = SHA256.HashData(Encoding.UTF8.GetBytes(script));
var base64Hash = Convert.ToBase64String(sha256Script);
Console.WriteLine(base64Hash);
third party resource
<meta http-equiv="Content-Security-Policy" content="default-src 'self' wss: https://192.168.1.152:44300">
<meta http-equiv="Content-Security-Policy" content="default-src 'self' wss: https://192.168.1.152:44300/script.js"> <script src="https://192.168.1.152:44300/script.js"></script>
我们可以指定信任的 origin,比如 https://192.168.1.152:44300 表示所有这个 origin 的 resource 都可以加载运行。
如果只是单个 resource 就写完整 URL,https://192.168.1.152:44300/script.js
如果我们不是很信任这个 origin 的 script,我们还可以添加一个 sha256 验证。
<script src="https://192.168.1.152:44300/script.js" integrity="sha256-tZpBEqmrY4CizbfYTAoo3wFhDJOpv6HGhMzwex2TTMs=" crossorigin="anonymous" ></script>
只要 resource 的内容和 hash 不匹配,那就会报错。
best practice
最起码可以 set 一个 https:,确保所有通信是加密的
<meta http-equiv="Content-Security-Policy" content="default-src https:">
‘self’,只相信自己也是一个好习惯。
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
对你相信的 thrid party 开放
<meta http-equiv="Content-Security-Policy" content="default-src 'self' https://192.168.1.152:44300">
只开放一些 third party resource
<meta http-equiv="Content-Security-Policy" content="default-src 'self' https://192.168.1.152:44300/script.js">
用 sha256 确保 script 是预期中的
<meta http-equiv="Content-Security-Policy" content="default-src 'self' wss: 'sha256-HgfVE1WaRXdD1n+LcUazTiP/FMatVgqvpPh9iAxr2qE='"> <script src="https://192.168.1.152:44300/script.js" integrity="sha256-tZpBEqmrY4CizbfYTAoo3wFhDJOpv6HGhMzwex2TTMs=" crossorigin="anonymous" ></script>
<script>alert('inline script');</script>
nonce
参考:MDN – nonce
nonce 是一个比较弱的防 hack 机制。用上面完整的 CSP 会更理想。

我是看到 Facebook Page Embed generate 出来的 code 有放,所以这里才顺便提一下。
假设我们没有用 sha256,'self' 这些 CSP 来防 hack,并且我们被 XSS 了。hacker 插入了一个 inline script 到我们的页面。
nonce 的防 hack 方式是这样,首先后端需要 generate nonce 随机数。
这里给一个 ASP.NET Core Razor Pages 的例子
public void OnGet()
{
static string GenerateCryptoNonce()
{
var rng = RandomNumberGenerator.Create(); byte[] bytes = new byte[16];
rng.GetBytes(bytes); string nonce = Convert.ToBase64String(bytes); return nonce;
} Nonce = GenerateCryptoNonce(); Response.Headers.Append("Content-Security-Policy", $"default-src 'self' wss: 'nonce-{Nonce}'");
}
nonce 需要用 cryptographically 128 bit (16 bytes) 生成,然后转 base64。
然后把 nonce 放到 CSP config 里,还有每一个 script 中。
<script nonce="@Model.Nonce">
alert('ok')
</script>
游览器在执行 script 之前,会先看它是否有 nonce,并且需要和 response header 中的 CSP nonce 匹配。
如果有匹配就执行,没有就不报错。
hacker 通过 XSS 插入的 script 没办法知道 nonce 随机数,所以最终 hacker script 不会被游览器执行,网页也就安全了。
了解了它的原理,确实,它也没有很安全,所以大家还是按上面 best practice 做会更理想。
frame-ancestors and X-Frame-Options
frame-ancestors 是用来取代 X-Frame-Options 的,它们的作用是声明网页是否允许被其它网页 iframe 嵌入。通常是不允许的啦。
注意:它只可以通过 HTTP header 方式去声明,HTML meta 不可以哦。

我的 Index 想嵌套 About 进来 iframe。如果没有 CSP 这个操作是 ok 的。

现在我们去配置 CSP 阻止它。

在 about 的 response header 加上 CSP frame-ancestors 'none' 完全不允许任何网页嵌入。
效果


只允许同域嵌入

把 'none' 换成 'self' 就可以了。
允许指定的 origin 嵌入

放入指定的 origin 就可以了,可以放多个,分隔符是空格。
defualt-src + frame-ancestors 的写法是
default-src 'self'; frame-ancestors https://192.168.1.152:44300 https://192.168.1.152:4200
分隔符是分号。
总结
CSP 是游览器的一种安全机制。可以用来限制 HTML 加载的 resource (e.g. script, img)。
比如限制 resource 只能是同域,或者指定可信赖的 origin。甚至可以通过 sha256 确保加载的内容是预期的。
另外它还可以防 XSS inline script 还有防网页被其它网页 ifram 嵌入等等。
这个是 Apple 官网返回的 CSP

安全 – CSP (Content Security Policy)的更多相关文章
- CSP(Content Security Policy) 入门教程
参考: http://www.ruanyifeng.com/blog/2016/09/csp.html https://developer.mozilla.org/en-US/docs/Web/HTT ...
- Content Security Policy (CSP) 介绍
当我不经意间在 Twitter 页面 view source 后,发现了惊喜. <!DOCTYPE html> <html lang="en"> <h ...
- 网页安全政策"(Content Security Policy,缩写 CSP)
作者:阿里聚安全链接:https://www.zhihu.com/question/21979782/answer/122682029来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...
- Content Security Policy (CSP)内容安全策略
CSP简介 Content Security Policy(CSP),内容(网页)安全策略,为了缓解潜在的跨站脚本问题(XSS攻击),浏览器的扩展程序系统引入了内容安全策略(CSP)这个概念. CSP ...
- Content Security Policy (CSP)内容安全策略总结
跨域脚本攻击 XSS 是最常见.危害最大的网页安全漏洞. 为了防止它们,要采取很多编程措施,非常麻烦.很多人提出,能不能根本上解决问题,浏览器自动禁止外部注入恶意脚本?这就是"网页安全政策& ...
- Refused to execute inline event handler because it violates the following Content Security Policy directive: "xxx". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...')
/********************************************************************************* * Refused to exec ...
- Content Security Policy的学习理解
以下内容转载自 http://www.cnblogs.com/alisecurity/p/5924023.html 跨域脚本攻击 XSS 是最常见.危害最大的网页安全漏洞. 为了防止它们,要采取很多编 ...
- Content Security Policy减少劫持
Content Security Policy减少劫持 什么是CSP? CSP是由单词 Content Security Policy 的首单词组成,是HTML5带给我们的一套全新主动防御的体系,旨在 ...
- Content Security Policy 入门教程
阮一峰文章:Content Security Policy 入门教程
- Content Security Policy介绍
Content Security Policy https://content-security-policy.com/ The new Content-Security-Policy HTTP re ...
随机推荐
- 今天我们来聊Java IO模型,BIO、NIO、AIO三种常见IO模型
一.写在开头 很久没更新喽,最近build哥一直在忙着工作,忙着写小说,都忘记学习自己的本职了,哈哈,不过现在正式回归! 我们继续学习Java的IO相关内容,之前我们了解到,所谓的IO(Input/O ...
- 3.3 Y86-64的顺序实现
将处理组织成阶段 为了实现流水线处理机制,要将指令组织成某个特殊的阶段序列,所有的指令遵循统一的序列,不同阶段放在不同硬件上进行处理.下面是对各阶段的简述. 取指(fetch):取指阶段从内存读取指令 ...
- js需要同时发起百条接口请求怎么办?--通过Promise实现分批处理接口请求
如何通过 Promise 实现百条接口请求? 实际项目中遇到需要发起上百条Promise接口请求怎么办? 前言 不知你项目中有没有遇到过这样的情况,反正我的实际工作项目中真的遇到了这种玩意,一个接口获 ...
- 手动设置提示在此环境中不可导入Django
手动设置提示在此环境中不可导入Django 环境参数添加manage.py中的代码'DJANGO_SETTINGS_MODULE', 'codeProject.settings'
- [rCore学习笔记 06]运行Lib-OS
QEMU运行第一章代码 切换分支 git checkout ch1 detail git checkout ch1 命令是用来切换到名为 ch1 的分支或者恢复工作目录中的文件到 ch1 提交的状态 ...
- 第十节 JMeter基础-初级购物车【接口关联-鉴权】
声明:本文所记录的仅本次操作学习到的知识点,其中商城IP错误,请自行更改. 背景:商城购物车可以添加数据,也可以删除数据. 思路: 登录后添加购物车,加入成功后查看购物车列表. 购物车列表,随机删除, ...
- 基于树莓派的OpenWrt系统打开蓝牙功能
在树莓派设备上的OpenWrt系统打开蓝牙功能 1. 安装必要的软件包 首先,你需要确保OpenWrt系统上安装了必要的蓝牙软件包.你可以通过OpenWrt的包管理器来安装它们.在OpenWrt系统上 ...
- SpringBoot实战:Spring Boot接入Security权限认证服务
引言 Spring Security 是一个功能强大且高度可定制的身份验证和访问控制的框架,提供了完善的认证机制和方法级的授权功能,是一个非常优秀的权限管理框架.其核心是一组过滤器链,不同的功能经由不 ...
- 小技巧:初始化后查看容器内某一bean的信息
1.debug 2. 3.与容器名对应,可以看到容器的对应信息 4.输入表达式可以直接获取对应结果信息,这里查看的是默认SpringSecurity过滤链的bean
- Jmeter函数助手20-eval
eval函数用于执行变量名.嵌套函数,允许在变量中的字符串中插入变量和函数引用 包含变量和函数引用的文本:填入变量名称或者函数或者字符,可以只填一种也可以组合都填入 1.eval函数填入的是变量名时则 ...