Vue进阶(三十三)Content-Security-Policy(CSP)详解

一、前言

跨域脚本攻击(XSSCross-Site Scripting)是最常见、危害最大的网页安全漏洞。XSS 攻击利用了浏览器对于从服务器所获取的内容的信任。恶意脚本在受害者的浏览器中得以运行,因为浏览器信任其内容来源,即使有的时候这些脚本并非来自于它本该来的地方。

为了防止它,要采取很多编程措施(比如大多数人都知道的转义、过滤HTML)。很多人提出,能不能根本上解决问题,即浏览器自动禁止外部注入恶意脚本?

这就是"内容安全策略"(Content Security Policy,缩写 CSP)的由来。

Content Security Policy (CSP) 是一种加固 Web 应用的安全性技术,通过在网站页面中设置 CSP Header 来限制页面中能够执行的脚本、样式、图片等资源。CSP 包括很多不同的策略,因此安全设置的具体值取决目标网站的需求和资源使用情况。一般而言,建议设置较为严格的 CSP,以避免 XSSCSRF 等安全问题。例如,可以配置以下 CSP:

Content-Security-Policy: default-src 'self'; script-src 'self' https://example.com; img-src 'self' data:; style-src 'self' 'unsafe-inline'; font-src 'self' https://example.com;

以上设置的 CSP 规则禁止所有来自第三方网站的资源,只允许本网站的资源加载。其中 script-src 只允许本网站和 example.com 的脚本加载,img-src 只允许本网站和 data: URI 的图片加载,style-src 只允许本网站和内联样式加载,font-src 只允许本网站和 example.com 的字体加载。请根据实际情况进行调整。

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

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

两种方法可以启用 CSP

  • 设置 HTTP 的 Content-Security-Policy 头部字段;
  • 设置网页的<meta>标签。

(1)使用HTTP的 Content-Security-Policy头部
在服务器端使用 HTTP的 Content-Security-Policy头部来指定安全策略:

Content-Security-Policy: policypolicy参数是一个包含了各种描述CSP策略指令的字符串。

示例1:

// index.js
const http = require('http');
const fs = require('fs');
http.createServer((req, res) => {
    
    
   const html = fs.readFileSync('index.html', 'utf8');
   res.writeHead(200, {
    
    
       'Content-Type': 'text-html',
       'Content-Security-Policy': 'default-src http: https:' 
   });
   res.end(html);
}).listen(9000);

console.log('server listening on 9000');

以上代码使用原生nodejs起了个服务,然后设置响应头部'Content-Security-Policy': 'default-src http: https:'表示只能通过外联的方式来引用jscss,如果使用内联的将报错:
在这里插入图片描述
示例2

只能在指定的域下加载文件,这里表示只能从同域下加载,斜杠为转义符:'Content-Security-Policy': 'default-src \'self\''

<script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>

在这里插入图片描述
打开控制台也可以看到请求在浏览器就已经被限制了:
在这里插入图片描述
如果要允许请求到这个域,添加进策略即可:

'Content-Security-Policy': 'default-src \'self\' https://cdn.bootcss.com/' 

示例3
上面的策略是无法限制form表单的提交的,如下列表单,点击后直接跳到了百度页面:

    <form action="https://baidu.com">
        <button>click me</button>
    </form>

这时候就要设置form-action策略:

'Content-Security-Policy': 'default-src \'self\' https://cdn.bootcss.com/; form-action \'self\''

在这里插入图片描述
其中,default-src设置的是全局,如果只想限制js的请求,可以将default-src改为script-src
启用违例报告
默认情况下,违规报告并不会发送。为启用发送违规报告,需要指定 report-uri策略指令,并提供至少一个URI地址去递交报告:

'Content-Security-Policy': 'script-src \'self\'; report-uri /report'

这里的报告我们可以直接在浏览器看到,它会自动发送一个请求出去:
在这里插入图片描述

如果只想收集报告,但是不真正的去限制请求,那怎么办?除了Content-Security-Policy,还有一个Content-Security-Policy-Report-Only字段,表示不执行限制选项,只是记录违反限制的行为。将头部改为这个即可。

如果 Content-Security-Policy-Report-Only 标头和 Content-Security-Policy 同时出现在一个响应中,两个策略均有效。在 Content-Security-Policy 标头中指定的策略有强制性,而 Content-Security-Policy-Report-Only 中的策略仅产生报告而不具有强制性。

使用meta标签
以上规则可以在浏览器端设置,如:

<meta http-equiv="Content-Security-Policy" content="form-action 'self';">

但与服务器端设置有点不同的是,meta无法使用report,只能在服务器端设置:
在这里插入图片描述

二、策略实施

限制方式

  • default-src: 限制全局,默认所有都会使用这种规则。
  • script-src: 限制JavaScript的源地址。
  • style-src:限制层叠样式表文件源。
  • img-src:限制图片和图标的源地址。
  • font-src:定义了字体加载的有效来源。
  • connect-src:定义了请求、XMLHttpRequestWebSocketEventSource 的连接来源
  • child-src: 指定定义了 web workers 以及嵌套的浏览上下文(如<frame><iframe>)的源。
  • media-src:限制通过 <audio><video><track> 标签加载的媒体文件的源地址。
  • object-src:限制 <object><embed> 标签的源地址。
  • manifest-src:限制应用声明文件的源地址。
  • prefetch-src:指定预加载或预渲染的允许源地址。
  • worker-src:限制 WorkerSharedWorkerServiceWorker 脚本源。
  • webrtc-src:指定WebRTC连接的合法源地址。

注⚠️: 被 object-src 控制的元素可能碰巧被当作遗留 HTML 元素,导致不支持新标准中的功能(例如 <iframe> 中的安全属性 sandboxallow)。因此建议限制该指令的使用(比如,如果可行,将 object-src 显式设置为 ‘none’)。
限制规则

  • self: 只允许同源下的资源。
  • unsafe-inline:允许使用内联资源,如内联的<script>元素、javascript: URL、内联的事件处理函数和内联的<style>元素。
  • unsafe-eval:允许使用 eval() 等通过字符串创建代码的方法。

注⚠️:设置多个资源,后面的会覆盖前面的!

一个CSP头由多组CSP策略组成,中间由分号分隔。其中每一组策略包含一个策略指令和一个内容源列表。例如:

Content-Security-Policy: default-src 'self' www.baidu.com; script-src 'unsafe-inline'

三、

使用插值表达式

{
    
    {
    
     message }}

使用双花括号语法来显示动态数据是 Vue 中最常用的方式。Vue 会将数据中的特殊字符进行转义,从而避免XSS攻击。变量 “message” 是一个安全的字符串,它不会受到攻击者的攻击。

使用指令

<div v-html="rawHtml"></div>

v-html 是一个常用指令,该指令使用原始HTML内容更新元素内容。但是,要注意使用该指令的危险性,因为它可以导致非常敏感的安全问题。Vue 会阻止注入恶意脚本,从而保护Web应用程序的安全性。

使用计算属性

<div>{
    
    {
    
     reversedMessage }}</div>
...
computed: {
    
    
reversedMessage: function () {
    
    
	return this.message.split('').reverse().join('')
}
}

Vue的计算属性可以让我们从不同的数据源派生数据。这样,以非必要的方式显示数据来防止XSS攻击。在计算属性中的数据被认为是安全的,不会被攻击者利用。

四、拓展阅读

猜你喜欢

转载自blog.csdn.net/sunhuaqiang1/article/details/132694439