一 目录

不折腾的前端,和咸鱼有什么区别

目录
一 目录
二 工作指标
三 SVG 简要介绍
四 SVG 破绽认知
 4.1 跨站脚本(XSS)
 4.2 HTML 注入
 4.3 XML 实体导致的 Billion Laughs 攻打
 4.4 Dos(拒绝服务):新型 SVG Billion Laughs 攻打
 4.5 XML 内部实体注入(XXE)
五 SVG 平安防护
 5.1 平安援用 SVG
 5.2 文件格式验证
 5.3 SVG 非法标签白名单列表
六 SVG 平安库
 6.1 DOMPurify 介绍
 6.2 DOMPurify 应用
 6.3 DOMPurify 源码分析
  6.3.1 DOMPurify v0.1
  6.3.2 DOMPurify v2.4.1
七 总结
八 参考资料

二 工作指标

返回目录

本篇文章的目标有:

  • [ ] 理解 SVG 破绽
  • [ ] 理解 SVG 常见防护伎俩
  • [ ] 搜查 SVG 数据安全性校验和过滤的库
  • [ ] 理解如何应用此类库来进行 SVG 上传防护
  • [ ] 浏览源码,能明确讲述此类库做了什么

如果对你有所帮忙,无妨点赞、评论、珍藏和吐槽一番~

三 SVG 简要介绍

返回目录

SVG 即可缩放矢量图形(Scalable Vector Graphics),它应用 XML 格局定义图像。

circle.svg
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">  <circle cx="100" cy="50" r="40" stroke="black"  stroke-width="2" fill="deepskyblue" /></svg>

关上 circle.svg,即可看到:

注:因后续 SVG 代码有些存有危害,请自行创立 xx.svg 文件来寄存,理解此 SVG 用处(甚至有些 SVG 倡议只看代码理解其攻击性即可,否则会卡本人机子)

SVG 更像是 HTML,而不单单是一张简略的图像。

例如,当设计师须要五彩斑斓的黑,咱们还能够间接批改下面 circle.svg 中的 fill="deepskyblue",将其改成 fill="black",想必设计师会十分开心,咱们又帮 ta 解决了一个难题~

此外,可缩放矢量也是 SVG 一大长处,毕竟能大能小还能清晰可见,放弃真本色,谁不喜爱呢~

更多的可自行返回 MDN 等网站理解:

  • MDN - SVG
  • 菜鸟教程 - SVG

四 SVG 破绽认知

返回目录

在下面,咱们理解到,SVG 更像是 (X)HTML,而不单单是一张简略的图像。

所以,在进行 SVG 平安防护之前,咱们尚需理解它的危害性。

4.1 跨站脚本(XSS)

返回目录

SVG 可通过 <script> 元素执行 JavaScript 代码。

所以,如果凋谢了 SVG 上传,那么会存在 XSS (跨站脚本)平安危险。

01-xss.svg
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">  <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="black" />  <!-- 这种操作,能够在 SVG 中间接执行 Script,从而通过 Ajax 将同域的 cookie 投出去,造成存储型 XSS -->  <script>alert(document.cookie)</script></svg>

注:如果在 Chrome 上通过 <img /> 标签引入,并不会触发攻打。然而,如果独自在 Tab 上关上图片,是会触发攻打的!!

又或者,咱们能够通过 SVG,让用户在查看图片的时候,伪装失落了明码,须要从新输出:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">  <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="black" />  <script>    const passwd = prompt('输出明码持续');    console.error('passwd: ', passwd);    alert(`感激你的明码:${passwd}`);  </script></svg>

4.2 HTML 注入

返回目录

SVG 是基于 XML 的矢量图,没法简略将 HTML 内容放到外面。

所以,SVG 提供了 <foreignObject> 元素,用来蕴含其余 XML 命名空间的元素。

这一部分数据很可能采纳 (X)HTML 模式。

02-html-injection
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">  <style>    div {      background: black;      color: pink;      font: 18px serif;      width: 100px;      height: 100px;      overflow: auto;    }  </style>  <foreignObject x="20" y="20" width="100" height="100">    <div xmlns="http://www.w3.org/1999/xhtml">      <a href="https://www.kdocs.cn">点击这里</a>      <p>超难看的内容等你来喔~</p>    </div>  </foreignObject></svg>

在这种状况下,咱们能够发动相似钓鱼、绕开同源策略、CSRF 之类的攻打。

如果在 Chrome 上通过 <img /> 标签引入,并不会渲染 <a> 标签,可能是 Chrome 做的防护,然而独自关上是会触发的

4.3 XML 实体导致的 Billion Laughs 攻打

返回目录

a billion laughs attack 是一种 denial-of-service(DoS)攻打,它次要作用于 XML 文档解析器。

它也被称为指数实体扩大攻打,是一种货真价实的 XML 炸弹。

在 SVG 中,能够通过 Entity 申明实体性能:

03-billion-laughs.svg
<!DOCTYPE lolz [<!ENTITY lol "lol"><!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"><!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"><!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"><!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;"><!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"><!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"><!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"><!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;"><!ENTITY lol10 "&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;"><!ENTITY lol11 "&lol10;&lol10;&lol10;&lol10;&lol10;&lol10;&lol10;&lol10;&lol10;"><!ENTITY lol12 "&lol11;&lol11;&lol11;&lol11;&lol11;&lol11;&lol11;&lol11;&lol11;"><!ENTITY lol13 "&lol12;&lol12;&lol12;&lol12;&lol12;&lol12;&lol12;&lol12;&lol12;"><!ENTITY lol14 "&lol13;&lol13;&lol13;&lol13;&lol13;&lol13;&lol13;&lol13;&lol13;"><!ENTITY lol15 "&lol14;&lol14;&lol14;&lol14;&lol14;&lol14;&lol14;&lol14;&lol14;">]><svg xmlns="http://www.w3.org/2000/svg">  <text x="0" y="20" font-size="20">    <lolz>&lol15;</lolz>  </text></svg>

浏览器关上这个文件后,CPU 间接干上 100%,所以如非必要,不要关上它。

4.4 Dos(拒绝服务):新型 SVG Billion Laughs 攻打

返回目录

除了 Entity,还有一种形式,就是通过 SVG 图像发动攻打。

其中 xlink:href 属性以 IRI(国内资源标识)形式定义了对某个资源的援用,该链接的具体含意需依据应用该链接的每个元素的上下文来决定。

<use> 元素从 SVG 文档中获取节点,而后将其复制到其余地位。

在上面代码中,咱们实现了重复嵌套应用,直至浏览器或者电脑卡死。

04-xlink-billion-laughs.svg
<svg version="1.2" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" xml:space="preserve"><path id="a" d="M0,0"/><g id="b"><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/></g><g id="c"><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/></g><g id="d"><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/></g><g id="e"><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/></g><g id="f"><use xlink:href="#e"/><use xlink:href="#e"/><use xlink:href="#e"/><use xlink:href="#e"/><use xlink:href="#e"/><use xlink:href="#e"/><use xlink:href="#e"/><use xlink:href="#e"/><use xlink:href="#e"/><use xlink:href="#e"/></g><g id="g"><use xlink:href="#f"/><use xlink:href="#f"/><use xlink:href="#f"/><use xlink:href="#f"/><use xlink:href="#f"/><use xlink:href="#f"/><use xlink:href="#f"/><use xlink:href="#f"/><use xlink:href="#f"/><use xlink:href="#f"/></g><g id="h"><use xlink:href="#g"/><use xlink:href="#g"/><use xlink:href="#g"/><use xlink:href="#g"/><use xlink:href="#g"/><use xlink:href="#g"/><use xlink:href="#g"/><use xlink:href="#g"/><use xlink:href="#g"/><use xlink:href="#g"/></g><g id="i"><use xlink:href="#h"/><use xlink:href="#h"/><use xlink:href="#h"/><use xlink:href="#h"/><use xlink:href="#h"/><use xlink:href="#h"/><use xlink:href="#h"/><use xlink:href="#h"/><use xlink:href="#h"/><use xlink:href="#h"/></g><g id="j"><use xlink:href="#i"/><use xlink:href="#i"/><use xlink:href="#i"/><use xlink:href="#i"/><use xlink:href="#i"/><use xlink:href="#i"/><use xlink:href="#i"/><use xlink:href="#i"/><use xlink:href="#i"/><use xlink:href="#i"/></g></svg>

4.5 XML 内部实体注入(XXE)

返回目录

这个危害没有在浏览器测试到,然而看他们说是存在的。

可能我的网络安全材料比拟不足,所以这里记录一下:

05-xxe.svg
 <!-- ubuntu 文件信息: file:///etc/passwd --> <!-- ubuntu 文件信息: file:///etc/hostname --><!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/hostname"> ]><svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">  <text font-size="16" x="0" y="16">&xxe;</text></svg> 

五 SVG 平安防护

返回目录

既然贸然应用 SVG 是有危险的,那么咱们必定要有所措施来应答应用。

  1. 限度 SVG 的危险标签。例如 <script><foreignObject>
  2. 限度 SVG 图像内加载资源和一些拓展逻辑
  3. 将 SVG 图片存储到其余服务器,避免次要服务器被攻打
  4. 限度 SVG 的援用形式,尽可能通过 <img> 标签等平安模式援用
  5. ……

5.1 平安援用 SVG

返回目录

DigiNinja 的 《Protecting against XSS in SVG》一文中,咱们能够看到 ta 对其的一些个人见解。

  • DigiNinja - Protecting against XSS in SVG

不举荐的

  • 「容易被攻打的」间接查看。这种间接链接并查看很危险
  • 「容易被攻打的」查看 iframe 中的图片
  • 「容易被攻打的」通过矢量图形进行消杀(?原文 Sanitised through Inkscape)。这种操作相似于间接查看,尽管它看起来像是被上面指令爱护
inkscape --file="xss.svg" --verb="FileVacuum" --export-plain-svg="sanitised.svg"

这个指令看起来像是移除了 JavaScript 代码,然而实际上并没有

举荐的

  • 「不容易被攻打的」在 Content-Disposition 响应标头查看
  • 「不容易被攻打的」设置查看元素的 CSP 白名单
  • 「不容易被攻打的」通过 <img> 标签加载。<img> 标签具备避免 JS 脚本攻打的性能
  • 「不容易被攻打的」设置标签的 CSP 白名单。通过下面的 <img> 标签,加上这个动作,能够进行双重爱护
  • 「不容易被攻打的」在 iframe 沙箱中查看图片。设置 iframe 的时候,须要设置 sandbox 属性,来防止脚本攻打

5.2 文件格式验证

返回目录

上面 2 个是不牢靠且能够被结构的:

  1. 文件名后缀
  2. 表单上传 Content-Type

所以,如果须要上传平安的 SVG,那么对其格局也须要进行验证。

判断文件类型的库:

  • Github - sindresorhus/file-type

5.3 SVG 非法标签白名单列表

返回目录

如下面所言,SVG 更像是 (X)HTML,所以须要过滤掉诸如 <script><foreignObject> 等相干标签和属性。

可参考的过滤清单:

  • Github - lizheming - svg-allow-tags.json
  • Github - DOMPurify - tags.js
  • Github - DOMPurify - attrs.js

六 SVG 平安库

返回目录

如果是本人写的话,那也太对不住你的用户了,毕竟你不晓得还有啥内容没防护到。

所以这里举荐一个库:DOMPurify

6.1 DOMPurify 介绍

返回目录

DOMPurify 从 2014.07 开始建设,截止指标 10.1k Star,仅有 2 个待解决 Issue。

兼容性方面,能够说十分到位:

  • Safari(10+)
  • Opera(15+)
  • IE(10+)
  • Edge
  • Firefox
  • Chrome

其余介绍:

  • 仓库自动测试覆盖面
  • 反对 TypeScript
  • 过滤尝试

6.2 DOMPurify 应用

返回目录

既然咱们的指标之一:

  • [x] 理解如何应用此类库来进行 SVG 上传防护

那么,理解怎么防护也是必要的,这里 jsliang 编写了一个实例:

index.html
<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">  <meta http-equiv="X-UA-Compatible" content="ie=edge">  <title>DOMPurify - jsliang</title>  <style>img { width: 300px; height: 300px; }</style>  <script src="./dist/purify.min.js"></script></head><body>  <p>请上传你的 svg 图片</p>  <input id="input" type="file" accept="image/*">  <div>    <!-- TODO: 批改为相应的占位图图片 -->    <img id="img" src="./img/placeholder.jpg" />  </div>  <script>    window.onload = () => {      const input = document.querySelector('#input');      const img = document.querySelector('#img');      // 监听文件上传,并以文本模式读取内容      const reader = new FileReader();      input.onchange = (e) => {        const [file] = input.files;        if (file) {          reader.readAsText(file);        };      };      // 对获取到的内容进行解决,并进行加载      reader.onload = (e) => {        const result = e.target.result;        const cleanResult = DOMPurify.sanitize(result);        console.error('过滤前: ', result);        console.error('过滤后: ', cleanResult);        const bolb = new Blob([cleanResult], {          type: 'image/svg+xml',        });        img.src = URL.createObjectURL(bolb);      };    };  </script></body></html>

那么,对于下述 SVG 代码,它的 Diff 比对为:

01-xss.svg
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">  <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="black" />-  <!-- 这种操作,能够在 SVG 中间接执行 Script,从而通过 Ajax 将同域的 cookie 投出去,造成存储型 XSS -->-  <script>alert(document.cookie)</script></svg>

是的,它会清理掉这个正文,并且把具备危害的 <script> 也给清理了。

那么,它是如何做到的?咱们接着往下看。

6.3 DOMPurify 源码分析

返回目录

对于 DOMPurify 源码分析,将划分 v0.1 版本的细讲,和 v2.4.1 版本的新增解说。

6.3.1 DOMPurify v0.1

返回目录

DOMPurify 的 v0.1 最后版本代码在 2014.03.01 开始打 Tag,地址为:DOMPurify v0.1

作为一个精美的小类库,我认为它的初始版本是十分具备参考性的,所以特意下载下来查看实现思路:

purify.js
;(function(root, factory) {  'use strict';  if (typeof define === "function" && define.amd) {    define(factory);  } else {    root.DOMPurify = factory();  }}(this, function() {  'use strict';  var DOMPurify = {};  DOMPurify.sanitize = function(dirty, cfg) {    // ... 其余内容  };  return DOMPurify;}));

咱们能够看到,它往以后环境挂载了 DOMPurify,且反对 2 种形式援用:

  1. 在 HTML 中援用:
// 挂载到诸如 window.DOMPurify 并应用var clean = DOMPurify.sanitize(dirty);
  1. 在 AMD 模式中援用:
require(['dompurify'], function(DOMPurify) {    var clean = DOMPurify.sanitize(dirty);};

此时,如果咱们注入的 dirty 如下述调用所示:

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">  <meta http-equiv="X-UA-Compatible" content="ie=edge">  <title>DOMPurify - 0.1 版本</title>  <script src="purify.js"></script></head><body>  <script>    window.onload = () => {      const svg = `<svg xmlns="http://www.w3.org/2000/svg" version="1.1">  <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="black" />  <!-- 这种操作,能够在 SVG 中间接执行 Script,从而通过 Ajax 将同域的 cookie 投出去,造成存储型 XSS -->  <script>alert(document.cookie)<\/script></svg>`;      debugger;      const clean = DOMPurify.sanitize(svg);      console.error('clean: ', clean);      /**       * 清理后,正文和 script 均移除:        <svg xmlns="http://www.w3.org/2000/svg">          <circle fill="black" stroke-width="2" stroke="black" r="40" cy="50" cx="100"></circle>                        </svg>       */    };  </script></body></html>

那么,它的代码调用程序是这样的:

代码 + 解说
// 步骤一,进入主函数DOMPurify.sanitize = function(dirty, cfg) {  // ... 其余内容};// 步骤二,判断传参,是否须要依据用户参数做配置cfg ? _parseConfig(cfg) : null;var _parseConfig = function(cfg) {  cfg.ALLOWED_ATTR    ? ALLOWED_ATTR    = cfg.ALLOWED_ATTR    : null;  // ...诸如 cfg.xxx,来配置参数};/** * @name 步骤三,初始化含脏数据的新 Document * @description * document.implementation 介绍 - https://javascript.ruanyifeng.com/dom/document.html#toc8 * document.implementation 属性返回一个 DOMImplementation 对象。该对象有三个办法,次要用于创立独立于以后文档的新的 Document 对象。 * 上面代码的作用,是将新创建的 Document 对象变为:<html>  <head></head>  <body>    <!-- 这里寄存传入的 dirty 脏数据 -->  </body></html> */// var dom = document.implementation.createHTMLDocument('');  dom.body.parentNode.removeChild(dom.body.parentNode.firstElementChild);  dom.body.outerHTML = dirty;var body = WHOLE_DOCUMENT ? dom.body.parentNode : dom.body;if (  !(dom.body instanceof HTMLBodyElement) ||  !(dom.body instanceof HTMLHtmlElement)) {  var freshdom = document.implementation.createHTMLDocument('');  body = WHOLE_DOCUMENT    ? freshdom.getElementsByTagName.call(dom,'html')[0]    : freshdom.getElementsByTagName.call(dom,'body')[0];}/** * @name 步骤四,创立新的节点,来寄存最终后果 * @description * document.createNodeIterator 介绍 - https://javascript.ruanyifeng.com/dom/document.html#toc28 * document.createNodeIterator 办法返回一个子节点遍历器 * 该实例的 nextNode() 办法和 previousNode() 办法,能够用来遍历所有子节点 *  */var _createIterator = function(doc) {  return document.createNodeIterator(    doc,    NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT,    function() { return NodeFilter.FILTER_ACCEPT; },    false  );};var currentNode;var nodeIterator = _createIterator(body);// 步骤五,迭代节点,清理标签和元素while (currentNode = nodeIterator.nextNode()) {  // 注 5-1:清理标签和元素:  if (_sanitizeElements(currentNode)) {    continue;  }  // 注 5-2:检测到 Shadow DOM,对其进行清理  if (currentNode.content instanceof DocumentFragment) {    _sanitizeShadowDOM(currentNode.content);  }  // 注 5-3:查看属性,如有必要则清理  _sanitizeAttributes(currentNode);}// 步骤六,清理结束,按须要返回数据(字符串或者 DOM)if (RETURN_DOM) {  return body;}return WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;

这外面的【注 5-1】【注 5-2】以及【注 5-3】代码分析如下所示:

注 5-1
// 通过 3 种伎俩,查看以后 Node 节点是否平安,如不平安,则删除之// 第 1 种伎俩是独立查看// 第 2 种是判断正文// 第 3 种是查看标签白名单(具体白名单能够看附件,这里不具体提醒)// 查看 JQ 的跳过不看var _sanitizeElements = function(currentNode) {  if (    // 注:_isClobbered 在下方独自解读    _isClobbered(currentNode)    || currentNode.nodeType === currentNode.COMMENT_NODE    || ALLOWED_TAGS.indexOf(currentNode.nodeName.toLowerCase()) === -1  ) {    currentNode.parentNode.removeChild(currentNode);    return true;  }  if (SAFE_FOR_JQUERY && !currentNode.firstElementChild) {    currentNode.textContent = currentNode.textContent.replace(/</g, '&lt;');  }  return false;};// _isClobbered: 查看具备攻击性的元素,如果返回 true 则代表具备攻击性,否则没有var _isClobbered = function(elm) {  if (    (elm.children && !(elm.children instanceof HTMLCollection))    || typeof elm.nodeName  !== 'string'    || typeof elm.textContent !== 'string'    || typeof elm.nodeType !== 'number'    || typeof elm.COMMENT_NODE !== 'number'    || typeof elm.setAttribute !== 'function'    || typeof elm.cloneNode !== 'function'    || typeof elm.removeAttributeNode !== 'function'    || typeof elm.attributes.item !== 'function'  ) {    return true;  }  return false;};
注 5-2
// 清理 Shadow DOMvar _sanitizeShadowDOM = function(fragment) {  var shadowNode;  var shadowIterator = _createIterator(fragment);  while (shadowNode = shadowIterator.nextNode()) {    // 注 5-1:清理标签和元素    if (_sanitizeElements(shadowNode)) {      continue;    }    // 递归查看 Shadow DOM    if (shadowNode.content instanceof DocumentFragment) {      _sanitizeShadowDOM(shadowNode.content);    }    // 注 5-3:查看属性,如有必要则清理    _sanitizeAttributes(shadowNode);  }};
注 5-3
// 清理属性var _sanitizeAttributes = function(currentNode) {  var regex = /^(\w+script|data):/gi,    clonedNode = currentNode.cloneNode();  for (var attr = currentNode.attributes.length-1; attr >= 0; attr--) {    var tmp = clonedNode.attributes[attr];    currentNode.removeAttribute(currentNode.attributes[attr].name);    if (tmp instanceof Attr) {      if (        (ALLOWED_ATTR.indexOf(tmp.name.toLowerCase()) > -1 ||        (ALLOW_DATA_ATTR && tmp.name.match(/^data-[\w-]+/i)))          && !tmp.value.replace(/[\x00-\x20]/g,'').match(regex)      ) {        currentNode.setAttribute(tmp.name, tmp.value);      }    }  }};

6.3.2 DOMPurify v2.4.1

返回目录
  • 版本地址:https://github.com/cure53/DOM...
  • 版本工夫:2022.11.10

这里次要看 DOMPurify.sanitize 局部源码更改:

  • 【新增】数据判空、数据格式问题、数据兼容
  • 【优化】配置项更加丰盛
  • 【新增】DOMPurify.removed 数组可查看被清理的元素
  • 【新增】传入的数据会先进行平安监测
  • 【新增】传入的数据类型更为丰盛(可为 DOM element)
  • 【优化】修复了一些 IE 等浏览器的兼容 bug
  • 【优化】迭代节点,清理标签和元素的代码更为欠缺(清理 Shadow DOM 的也优化了)
  • 【新增】条件容许会序列化 doctype
  • 【新增】条件容许会对最初的数据通过 template-safe 再清理一次
  • 【优化】标签白名单和属性白名单更加丰盛健全了

具体的这里就不一一解说了,感兴趣的小伙伴能够自行返回下面版本地址下载和理解。

七 总结

返回目录

通过这一系列的操作,咱们能够给结尾的工作指标划上句号啦~

  • [x] 理解 SVG 破绽
  • [x] 理解 SVG 常见防护伎俩
  • [x] 搜查 SVG 数据安全性校验和过滤的库
  • [x] 理解如何应用此类库来进行 SVG 上传防护
  • [x] 浏览源码,能明确讲述此类库做了什么

欢送小伙伴们点赞、评论、珍藏和吐槽,我是 jsliang,下篇文章见~

八 参考资料

返回目录

优良网站:

  • MDN - SVG
  • 菜鸟教程 - SVG
  • FreeBuf 网络安全行业门户

参考文献:

  • 某某某在搬砖 - 从黑产的角度看文件上传平安之svg文件
  • 知乎 - 怡红公子 - Web 安全漏洞之文件上传
  • 平安客 - 興趣使然的小胃 - SVG在Web攻打中的利用
  • CSDN - 帅气的吴先生 - billion laughs attack
  • srcmini - 什么是.NET Framework C#Xml Parser上的Billion Laughs XML DoS攻打
  • freebuf - 山石网科 - SVG简介
  • 腾讯云 - FB客服 - 平安钻研 | 利用图片上传性能实现存储型XSS
  • 知乎 - 合天网安实验室 - 浅谈SVG的两个黑魔法
  • DigiNinja - SVG XSS Defence Scenarios
  • Github - digininja/svg_xss
  • DigiNinja - Protecting against XSS in SVG
  • 简书 - book4yi - 文件上传利用Tips
  • FinClip小程序里如何平安应用SVG
  • StackOverflow - Change default text in input type="file"?
  • How to handle SVG
  • MDN - FileReader.readAsText()
  • StackOverflow - HTML5 File API: How to see the result of readAsText()
  • 掘金 - redmed - SVG 在 image 标签中的动静批改技巧
  • Github - lizheming - svg-allow-tags.json
  • Github - sindresorhus/file-type
  • Github - DOMPurify - tags.js
  • Github - DOMPurify - attrs.js

不折腾的前端,和咸鱼有什么区别!

感觉文章不错的小伙伴欢送点赞/点 Star。

如果小伙伴须要分割 jsliang

  • Github
  • 掘金

集体联系方式寄存在 Github 首页,欢送一起折腾~

争取打造本人成为一个充斥摸索欲,喜爱折腾,乐于扩大本人知识面的一生学习斜杠程序员。

jsliang 的文档库由 梁峻荣 采纳 常识共享 署名-非商业性应用-雷同形式共享 4.0 国内 许可协定 进行许可。<br/>基于 https://github.com/LiangJunrong/document-library 上的作品创作。<br/>本许可协定受权之外的应用权限能够从 https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 处取得。