优化富文本入库时引起的XSS漏洞

511 阅读1分钟

前言

在平时使用的富文本编辑器中也会存在恶意输入JS脚本

使用js-xss 对文本进行过滤,删除掉可能存在的脚本

安装

NPM
 npm install xss
Bower
 bower install xss

使用

在Node中使用
 var xss = require("xss");
 var html = xss('<script>alert("xss");</script>');
 console.log(html);
浏览器中使用
 <script src="https://rawgit.com/leizongmin/js-xss/master/dist/xss.js"></script>
 <script>
 // 使用函数名 filterXSS,用法一样
 var html = filterXSS('<script>alert("xss");</scr' + 'ipt>');
 alert(html);
 </script>
语法

xss接收两个参数,第一个参数 HtmlString 需要被处理的html字符串,第二个参数 options 如何处理 hmtl 的配置项

 /*
 * 只允许a标签,该标签只允许href, title, target这三个属性
 var options = {
   // 白名单
   whiteList: {
     a: ["href", "title", "target"]
   },
   // 过滤掉不再白名单的标签
   stripIgnoreTag: true,
   // script标签较特殊,需要过滤标签中间的内容
   stripIgnoreTagBody: ["script"],
   // 更多文档 https://gitee.com/meiyou_ruguo/js-xss?_from=gitee_search
 };
 */
 const = options = {}; // 自定义规则
 const html = xss('<script>alert("xss");</script>', options);
项目中使用
 const xss = require("xss");
 function getDefaultWhiteList() {
     return {
         a: ["target", "href", "title"],
         abbr: ["title"],
         address: [],
         area: ["shape", "coords", "href", "alt"],
         article: [],
         aside: [],
         audio: ["autoplay", "controls", "loop", "preload", "src"],
         b: [],
         bdi: ["dir"],
         bdo: ["dir"],
         big: [],
         blockquote: ["cite"],
         br: [],
         caption: [],
         center: [],
         cite: [],
         code: [],
         col: ["align", "valign", "span", "width"],
         colgroup: ["align", "valign", "span", "width"],
         dd: [],
         del: ["datetime"],
         details: ["open"],
         div: [],
         dl: [],
         dt: [],
         em: [],
         font: ["color", "size", "face"],
         footer: [],
         h1: [],
         h2: [],
         h3: [],
         h4: [],
         h5: [],
         h6: [],
         header: [],
         hr: [],
         i: [],
         img: ["src", "alt", "title", "width", "height"],
         ins: ["datetime"],
         li: [],
         mark: [],
         nav: [],
         ol: [],
         p: [],
         pre: [],
         s: [],
         section: [],
         small: [],
         span: [],
         sub: [],
         sup: [],
         strong: [],
         table: ["width", "border", "align", "valign","style"],
         tbody: ["align", "valign"],
         td: ["width", "rowspan", "colspan", "align", "valign","style"],
         tfoot: ["align", "valign"],
         th: ["width", "rowspan", "colspan", "align", "valign"],
         thead: ["align", "valign"],
         tr: ["rowspan", "align", "valign"],
         tt: [],
         u: [],
         ul: [],
         video: ["autoplay", "controls", "loop", "preload", "src", "height", "width"],
         style:[]   //新添
     };
 }
 const options = {
     whiteList: getDefaultWhiteList(),
     stripIgnoreTag: true,
     stripIgnoreTagBody: ['script']
 }
 let editorHtml = editor.txt.html() // 确保这里拿到的是 <script>xxx</script>,如果是 &lt;xxx&gt; 则需要替换
 // 替换 &lt; &gt;
 // editor.txt.html().replaceAll('&lt;', '<').replaceAll('&gt;', '>');
 const html = xss(editorHtml, options);
 console.log(html);

总结

  • 富文本形式输入脚本的形式是 存储型 xss ,提交的数据存在脚本,并且保存成功。其他人访问当前页面就会触发
  • 开启 httponly (禁止JS获取Cookie)
  • 输入过滤,输出转义