安全 – 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 ...
随机推荐
- 4 - 【RocketMQ 系列】CentOS 7.6 安装部署RocketMQ
五.自启动脚本 1.rocketmq 服务脚本 cd /etc/init.d vim rocketmq 把下面内容填好后 按ESC 再输入 :wq! 保存退出 之后再修改权限 chmod 777 ro ...
- IP协议学习笔记
目录 IP地址格式 IP分类 CIDR 和 子网掩码介绍 NAT+公网.私网地址 CIDR 与 VLSM VLSM 子网划分案例 练习 Reference IP的作用类似物理世界中的地址,用于定位机器 ...
- 基于微信小程序+Springboot线上租房平台设计和实现【三端实现小程序+WEB响应式用户前端+后端管理】
感兴趣的可以先收藏起来,大家在毕设选题,项目以及论文编写等相关问题都可以给我加好友咨询 一. 前言介绍: 近年来,我国的社会经济迅猛发展,社会对于房屋租赁的需求也在不断增多.在房屋租赁企业中面对繁琐而 ...
- oeasy 教您玩转 linux 010214 画面转文字 asciiview
- oeasy教您玩转python - 4 - # 调试程序
调试程序 回忆上次内容 py 的程序都是写在明面上的 所有需要执行的事情都明着写到了 py 文件中 用 python3 解释 py 文件进行执行 可以下载人家写好的 py 文件 下载的 py 文件 ...
- njs最详细的入门手册:Nginx JavaScript Engine
原文链接:https://hi.imzlh.top/2024/07/08.cgi 关于njs 首先,njs似乎在国内外都不受关注,资料什么的只有 官网参考手册,出了个问题只能看到Github Issu ...
- mybatis源码配置文件解析之五:解析mappers标签(解析class属性)
在上篇文章中分析了mybatis解析mapper标签中的resource.url属性的过程,<mybatis源码配置文件解析之五:解析mappers标签(解析XML映射文件)>.通过分析可 ...
- .NET周刊【7月第4期 2024-07-28】
国内文章 .NET 高性能缓冲队列实现 BufferQueue https://mp.weixin.qq.com/s/fUhJpyPqwcmb3whuV3CDyg BufferQueue 是一个用 . ...
- Python和RPA网页自动化-让非标准下拉框选择指定文本的方法
以下方"节点审批"下拉框为例 该下拉框没有<select>标签,而是<div><ul><li>标签.分别使用Python和RPA网页 ...
- 《最新出炉》系列初窥篇-Python+Playwright自动化测试-60 - 判断元素是否显示 - 下篇
1.简介 有些页面元素的生命周期如同流星一闪,昙花一现.我们也不知道这个元素在没在页面中出现过,为了捕获这一美好瞬间,让其成为永恒.我们就来判断元素是否显示出现过. 在操作元素之前,可以先判断元素的状 ...