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


    一、前言

    作为前端工程师你真的了解 XSS 吗?越来越多超级应用基于 Web 构建,如何系统的攻防 XSS 尤为重要。微软安全工程师 1999 年底披露了 XSS,22 年来 XSS 一直稳居 OWASP开放 Web 应用程序安全 ) 报告的前 TOP10。

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

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

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

    二、XSS 攻击都有哪些类型?

    基于应用的 XSS 攻击主要有以下类型:

    • 反射 XSS (RXSS):当作为 HTTP 请求的⼀部分提供的恶意数据在未经过适当清理的情况下成为服务器响应的⼀部分时,就会发⽣ RXSS 攻击。因此,嵌⼊在 HTTP 响应中的恶意数据会返回客⼾端并在浏览器呈现时执⾏。RXSS 的典型⽬标是具有搜索功能的 Web 应⽤程序,其中嵌⼊的恶意数据成为搜索结果或错误消息的⼀部分。
    • 存储型 XSS (SXSS):当以输⼊形式提供的恶意数据未经清理就存储在服务器应⽤程序数据库或⽂件中时,就会出现 SXSS 攻击。SXSS 攻击的典型⽬标是在线社交⽹络应⽤程序和论坛,恶意数据可以在其中发布、存储在数据库中,从⽽感染访问它们的每个⽤⼾。SXSS 攻击也称为持久性攻击。
    • DOM XSS (DXSS):DXSS 攻击是渲染时攻击。DOM-based XSS攻击是一种与服务器没有直接交互的攻击,它利用客户端代码中的漏洞来实现攻击。攻击者通常会在页面上运行可执行代码,例如链接、表单等,来利用客户端脚本来注入恶意代码。与 RXSS 和 SXSS 相反, DXSS 攻击中使⽤的恶意数据⽤于动态更改浏览器在渲染阶段⽣成的 DOM 树。
    • JavaScript Mimicry XSSJSM-XSS):攻击者不是注⼊恶意脚本,⽽是利⽤ Web 应⽤程序中已经使⽤的脚本来发起 JSM-XSS 攻击。JSM-XSS 攻击很难被检测到并且很容易通过基于⽩名单的过滤器。
    • XSS 蠕⾍(WXSS):WXSS 攻击是具有⾃我复制能⼒的 XSS 攻击。RXSS 和 SXSS 攻击被归类为 WXSS。WXSS 攻击更加危险,因为它们在 Web 应⽤程序⽤⼾之间传播,并随着时间的推移逐渐感染其他⽤⼾。此类攻击的典型⽬标是在线社交⽹络应⽤程序。

    三、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;
    
    • 1

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

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

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

    两种方法可以启用 CSP

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

    3.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');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    以上代码使用原生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>
    
    • 1

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

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

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

        <form action="https://baidu.com">
            <button>click mebutton>
        form>
    
    • 1
    • 2
    • 3

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

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

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

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

    这里的报告我们可以直接在浏览器看到,它会自动发送一个请求出去:
    在这里插入图片描述
    如果只想收集报告,但是不真正的去限制请求,那怎么办?除了Content-Security-Policy,还有一个Content-Security-Policy-Report-Only字段,表示不执行限制选项,只是记录违反限制的行为。将头部改为这个即可。

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

    3.2 使用 meta 标签

    以上规则可以在浏览器端设置,如:

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

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

    四、CSP 实施策略

    限制方式

    • default-src: 限制全局,默认所有都会使用这种规则。
    • script-src: 限制JavaScript的源地址。
    • style-src:限制层叠样式表文件源。
    • img-src:限制图片和图标的源地址。
    • font-src:定义了字体加载的有效来源。
    • connect-src:定义了请求、XMLHttpRequestWebSocketEventSource 的连接来源
    • child-src: 指定定义了 web workers 以及嵌套的浏览上下文(如