【问题标题】:How to check if string of HTML is safe?如何检查 HTML 字符串是否安全?
【发布时间】:2011-11-10 07:17:43
【问题描述】:

在我的应用程序中,我需要以字符串形式发送和接收 HTML。我想保证事情的安全,因此我需要检查字符串中的 dom 元素是否匹配允许的标签,以及样式声明是否有效,以及是否没有注入的脚本。首先想到的当然是对字符串进行正则表达式,但这很乏味,可能是错误的并且肯定是低效的。第二个想法是使用一种叫做 XPath 的东西,但是即使我已经阅读了 MDN 网站上的一些资料,我仍然不知道如何实现这个示例代码:

const XPathResult           = Components.interfaces.nsIDOMXPathResult;

const ALLOWED_TAGS          = ['div', 'span', 'b', 'i', 'u', 'br', 'font', 'img'];
const ALLOWED_STYLES        = ['font-weight', 'font-size', 'font-family', 'text-decoration', 'color', 'background-color'];
const ALLOWED_ATTRIBUTES    = ['style', 'name'];

const XPATH_PART_TAGS = ALLOWED_TAGS.map(function (v) {
    return "name() != '" + v + "' and name() != '" + v.toUpperCase() + "'"; // case insensitive
}).join(' and ');

const XPATH_PART_ATTRS = ALLOWED_ATTRIBUTES.map(function (v) {
    return "name() != '" + v + "' and name() != '" + v.toUpperCase() + "'"; // case insensitive
}).join(' and ');


const XPATH_BAD_TAGS        = "//*[(namespace-uri() != 'http://www.w3.org/1999/xhtml') or (" + XPATH_PART_TAGS + ")]";
const XPATH_BAD_ATTRIBUTES  = "//@*[((namespace-uri() != 'http://www.w3.org/1999/xhtml') and (namespace-uri() != '')) or (" + XPATH_PART_ATTRS+ ")]";
const XPATH_STYLE           = "//@*[name() = 'style']";


/**
 * Checks if inline style definition is considered secure
 *
 * @param {String} styleValue value of style attribute
 * @return bool
 */
function isStyleSecure(styleValue) {
    var styles = styleValue.split(';'),
        style,
        name, value,
        i, l;
    for (i = 0, l = styles.length; i < l; i++) {
        style = styles[i].trim();
        if (style === '') {
            continue;
        }
        style = style.split(':', 2);
        if (style.length !== 2) {
            return false;
        }
        name = style[0].trim().toLowerCase();
        value = style[1].trim();

        if (ALLOWED_STYLES.indexOf(name) === -1) {
            return false;
        }
    }
    return true;
}

/**
 * Singleton that verifies if given XHTML document fragment is considered secure.
 * Uses whitelist-based checks on tag names, attribute names and document namespaces.
 *
 * @class
 * @namespace core.SecurityFilter.MessageSecurityFilter
 */
var MessageSecurityFilter = {
    /**
     * Checks if given document fragment is safe
     *
     * @param {nsIDOMElement} element root element of the XHTML document fragment to analyze
     * @return {bool} true if fragment is safe, false otherwise
     */
    isSecure: function SecurityFilter_isSecure(element) {
        var document = element.ownerDocument,
            result,
            attr;

        result = document.evaluate('//*', element, null, XPathResult.ANY_TYPE, null);

        result = document.evaluate(XPATH_BAD_TAGS, element, null, XPathResult.ANY_TYPE, null);
        if (result.iterateNext()) {
            return false;
        }
        result = document.evaluate(XPATH_BAD_ATTRIBUTES, element, null, XPathResult.ANY_TYPE, null);
        if ((attr = result.iterateNext())) {
            return false;
        }

        result = document.evaluate(XPATH_STYLE, element, null, XPathResult.ANY_TYPE, null);
        while ((attr = result.iterateNext())) {
            if (!isStyleSecure(attr.nodeValue)) {
                return false;
            }
        }

        return true;
    }

};

第一个想法是创建 documentFragment,然后使用 treeWalker 或仅使用 .firstChild 等跟随 dom 树检查它的节点。但我想这个解决方案是不安全的,因为它会让我对所有注入的脚本开放。我说的对吗?

还有其他方法吗?

【问题讨论】:

  • 确保你在服务器端做同样的事情...
  • 编写自己的 HTML 净化器的问题是大多数时候人们试图清理有效的 HTML,但是浏览器设置为处理无效的 SGML,因此存在许多用户可以使用的漏洞正在上传一些看似无效的 HTML,但实际上有效,而您的净化器从未捕获到这些内容。最好采用社区中已有的版本,如果您觉得自己发现了漏洞,请提交更新 - 帮助大家。

标签: javascript html dom xpath


【解决方案1】:

您需要的安全级别取决于您处理 HTML 的方式。如果您通过电子邮件发送它或将其显示在网络服务器上,则需要比仅对其进行文本分析要小心得多。

假设您在 Web 服务器上显示此内容,这是一个非常困难的问题,您应该使用 HTML 净化器,例如 http://htmlpurifier.org/订阅安全更新,甚至可以找到自动获取更新的方法。为了提高安全性,使用 iframe。如果您以某种方式转义 HTML,也要特别注意。

当然,根据问题的实际情况,正确答案可能会完全不同。以上应该处理最常见的情况。

另见RegEx match open tags except XHTML self-contained tags

【讨论】:

    【解决方案2】:

    不要自己滚动消毒剂。使用由了解 HTML、CSS 和 JS 的黑暗丑陋角落的人编写的。

    请参阅 http://code.google.com/p/google-caja/wiki/JsHtmlSanitizer 了解 JavaScript 清理程序。

    【讨论】:

      猜你喜欢
      • 2013-03-05
      • 1970-01-01
      • 2011-03-15
      • 2010-09-24
      • 2016-12-17
      • 2018-01-16
      • 2015-10-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多