当前位置:  开发笔记 > 编程语言 > 正文

在客户端清理/重写HTML

如何解决《在客户端清理/重写HTML》经验,为你挑选了7个好方法。

我需要显示通过跨域请求加载的外部资源,并确保只显示" 安全 "内容.

可以使用Prototype的String#stripScripts删除脚本块.但处理程序如onclickonerror仍在那里.

是否有任何图书馆至少可以

剥离脚本块,

杀死DOM处理程序,

删除黑名单标签(例如:embedobject).

那里有任何与JavaScript相关的链接和示例吗?



1> Mike Samuel..:

2016年更新:现在有一个基于Caja清洁剂的Google Closure软件包.

它有一个更干净的API,被重写以考虑现代浏览器上可用的API,并与Closure Compiler更好地交互.


无耻的插件:请参阅caja/plugin/html-sanitizer.js以获取经过全面审核的客户端html清理程序.

它是白名单,不是黑名单,但白名单可根据CajaWhitelists进行配置


如果要删除所有标记,请执行以下操作:

var tagBody = '(?:[^"\'>]|"[^"]*"|\'[^\']*\')*';

var tagOrComment = new RegExp(
    '<(?:'
    // Comment body.
    + '!--(?:(?:-*[^->])*--+|-?)'
    // Special "raw text" elements whose content should be elided.
    + '|script\\b' + tagBody + '>[\\s\\S]*?[\\s\\S]*?',
    'gi');
function removeTags(html) {
  var oldHtml;
  do {
    oldHtml = html;
    html = html.replace(tagOrComment, '');
  } while (html !== oldHtml);
  return html.replace(/

人们会告诉你,你可以创建一个元素,然后分配innerHTML然后获取innerTextor textContent,然后转义实体.不要那样做.它易受XSS注入攻击,因为即使节点从未附加到DOM,也会运行onerror处理程序.


好的,看起来这里有一些文档:http://code.google.com/p/google-caja/wiki/JsHtmlSanitizer
Caja HTML清理程序代码看起来很棒,但需要一些粘合代码(邻近的`cssparser.js`,但更重要的是`html4`对象).此外,它污染了全局`window`属性.这个代码是否有这个网页版本?如果没有,您是否看到更好的生产和维护方法,而不是为其创建单独的项目?
@phihag那个包是针对nodejs而不是浏览器的.

2> Jeffery To..:

通过将Google Caja HTML清理程序嵌入到Web工作者中,可以使其成为"Web就绪" .清理程序引入的任何全局变量都将包含在worker中,并且处理在其自己的线程中进行.

对于不支持Web Workers的浏览器,我们可以使用iframe作为清洁工的独立环境.Timothy Chien有一个polyfill就是这样做的,使用iframe模拟Web Workers,这样就可以为我们完成.

Caja项目有一个wiki页面,介绍如何使用Caja作为独立的客户端清洁剂:

签出源代码,然后运行构建 ant

包括html-sanitizer-minified.jshtml-css-sanitizer-minified.js在您的网页

呼叫 html_sanitize(...)

工作者脚本只需要遵循这些说明:

importScripts('html-css-sanitizer-minified.js'); // or 'html-sanitizer-minified.js'

var urlTransformer, nameIdClassTransformer;

// customize if you need to filter URLs and/or ids/names/classes
urlTransformer = nameIdClassTransformer = function(s) { return s; };

// when we receive some HTML
self.onmessage = function(event) {
    // sanitize, then send the result back
    postMessage(html_sanitize(event.data, urlTransformer, nameIdClassTransformer));
};

(需要更多代码才能使simworker库正常工作,但这对于此讨论并不重要.)

演示:https://dl.dropbox.com/u/291406/html-sanitize/demo.html



3> Sean Edwards..:

永远不要相信客户.如果您正在编写服务器应用程序,请假设客户端将始终提交不卫生的恶意数据.这是一个经验法则,可以帮助您摆脱困境.如果可以的话,我会建议在服务器代码中进行所有验证和卫生,你知道(在合理的程度上)将无法摆弄.也许您可以使用服务器端Web应用程序作为客户端代码的代理,该代码从第三方获取并在将其发送到客户端之前进行卫生处理?

[编辑]对不起,我误解了这个问题.但是,我坚持我的建议.如果您在将服务器发送给服务器之前清理服务器,那么您的用户可能会更安全.


实际上,随着node.js的普及,javascript解决方案也可能是一个服务器端解决方案.这就是我至少在这里结束的方式.不过,这是一个很好的建议.

4> bobince..:

您无法预料到某些浏览器可能会绊倒以逃避黑名单的每种可能的奇怪类型的格式错误标记,因此请勿列入黑名单.有许多你可能需要的不仅仅是脚本/嵌入/对象和处理程序,除去更多的结构.

而是尝试将HTML解析为层次结构中的元素和属性,然后针对尽可能小的白名单运行所有元素和属性名称.还要检查您对白名单所允许的任何URL属性(请记住,有更多危险的协议,而不仅仅是javascript :).

如果输入是格式良好的XHTML,则上述的第一部分要容易得多.

像往常一样,如果您可以找到任何其他方法来避免这样做,请改为使用它.有许多潜在的漏洞.如果主要的网络邮件服务在这么多年后仍在寻找漏洞,那么是什么让你觉得你可以做得更好?



5> aldel..:

现在所有主流浏览器都支持沙盒iframe,我认为有一种更简单的方法可以保证安全.如果这个答案可以由更熟悉这种安全问题的人审查,我会喜欢它.

注意:此方法肯定不适用于IE 9及更早版本.有关支持沙盒的浏览器版本,请参阅此表.

我们的想法是在禁用JavaScript的情况下创建隐藏的iframe,将不受信任的HTML粘贴到其中,然后让它进行解析.然后,您可以遍历DOM树并复制出被认为安全的标记和属性.

此处显示的白名单只是示例.白名单的最佳选择取决于应用程序.如果您需要比标签和属性的白名单更复杂的策略,则可以通过此方法来适应,但不是通过此示例代码.

var tagWhitelist_ = {
  'A': true,
  'B': true,
  'BODY': true,
  'BR': true,
  'DIV': true,
  'EM': true,
  'HR': true,
  'I': true,
  'IMG': true,
  'P': true,
  'SPAN': true,
  'STRONG': true
};

var attributeWhitelist_ = {
  'href': true,
  'src': true
};

function sanitizeHtml(input) {
  var iframe = document.createElement('iframe');
  if (iframe['sandbox'] === undefined) {
    alert('Your browser does not support sandboxed iframes. Please upgrade to a modern browser.');
    return '';
  }
  iframe['sandbox'] = 'allow-same-origin';
  iframe.style.display = 'none';
  document.body.appendChild(iframe); // necessary so the iframe contains a document
  iframe.contentDocument.body.innerHTML = input;

  function makeSanitizedCopy(node) {
    if (node.nodeType == Node.TEXT_NODE) {
      var newNode = node.cloneNode(true);
    } else if (node.nodeType == Node.ELEMENT_NODE && tagWhitelist_[node.tagName]) {
      newNode = iframe.contentDocument.createElement(node.tagName);
      for (var i = 0; i < node.attributes.length; i++) {
        var attr = node.attributes[i];
        if (attributeWhitelist_[attr.name]) {
          newNode.setAttribute(attr.name, attr.value);
        }
      }
      for (i = 0; i < node.childNodes.length; i++) {
        var subCopy = makeSanitizedCopy(node.childNodes[i]);
        newNode.appendChild(subCopy, false);
      }
    } else {
      newNode = document.createDocumentFragment();
    }
    return newNode;
  };

  var resultElement = makeSanitizedCopy(iframe.contentDocument.body);
  document.body.removeChild(iframe);
  return resultElement.innerHTML;
};

你可以在这里试试.

请注意,我在此示例中禁止使用样式属性和标记.如果你允许它们,你可能想要解析CSS并确保它对你的目的是安全的.

我已经在几个现代浏览器(Chrome 40,Firefox 36 Beta,IE 11,Chrome for Android)和一个旧版本(IE 8)上进行了测试,以确保在执行任何脚本之前保存它.我有兴趣知道是否有任何浏览器有问题,或者我忽视的任何边缘情况.


这篇文章值得专家们关注,因为它似乎是一个显而易见且最简单的解决方案.它真的安全吗?

6> ericsoco..:

所以,它是2016年,我想我们很多人现在都在使用npm代码中的模块.sanitize-html似乎是npm的主要选项,尽管还有其他选项.

这个问题的其他答案提供了很好的输入,如何推出自己的,但这是一个棘手的问题,经过充分测试的社区解决方案可能是最好的答案.

在命令行上运行以安装: npm install --save sanitize-html

ES5: var sanitizeHtml = require('sanitize-html'); // ... var sanitized = sanitizeHtml(htmlInput);

ES6: import sanitizeHtml from 'sanitize-html'; // ... let sanitized = sanitizeHtml(htmlInput);


2018年,这太重了(半兆字节的依赖)

7> neu-rah..:
String.prototype.sanitizeHTML=function (white,black) {
   if (!white) white="b|i|p|br";//allowed tags
   if (!black) black="script|object|embed";//complete remove tags
   var e=new RegExp("(<("+black+")[^>]*>.*|(?!<[/]?("+white+")(\\s[^<]*>|[/]>|>))<[^<>]*>|(?!<[^<>\\s]+)\\s[^]+(?=[/>]))", "gi");
   return this.replace(e,"");
}

- 黑名单 - >完整删除标签和内容

- 白名单 - >保留标签

删除其他标签但保留标签内容

- 删除了白名单标签的所有属性(其余的)


当你执行` ipt>`时会发生什么?去除实际上可能更糟.有时仅仅完全记录该用户并且不尝试修复它是值得的.
那个`e`变量看起来像是一个无意识的全局.否则这适合我的需要.
推荐阅读
N个小灰流_701
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有