Javascript 如何检查HTML字符串是否安全?
在我的应用程序中,我需要以字符串形式发送和接收HTML。我希望保持安全,因此我需要检查字符串中的dom元素是否与允许的标记匹配,样式声明是否有效,以及是否没有注入脚本。首先想到的当然是重新设置字符串,但这很乏味,可能有问题,而且效率肯定很低。第二个想法是使用XPath,但即使我在MDN站点上阅读了一些资料,我仍然不知道如何实现此示例代码:Javascript 如何检查HTML字符串是否安全?,javascript,html,dom,xpath,Javascript,Html,Dom,Xpath,在我的应用程序中,我需要以字符串形式发送和接收HTML。我希望保持安全,因此我需要检查字符串中的dom元素是否与允许的标记匹配,样式声明是否有效,以及是否没有注入脚本。首先想到的当然是重新设置字符串,但这很乏味,可能有问题,而且效率肯定很低。第二个想法是使用XPath,但即使我在MDN站点上阅读了一些资料,我仍然不知道如何实现此示例代码: const XPathResult = Components.interfaces.nsIDOMXPathResult; const A
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;
}
};
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'];
常量XPATH\u PART\u TAGS=允许的\u TAGS.map(函数(v){
返回“name()!=”“+v+””和name()!=”“+v.toUpperCase()+”;//不区分大小写
}).加入(‘and’);
常量XPATH\u PART\u ATTRS=允许的属性.map(函数(v){
返回“name()!=”“+v+””和name()!=”“+v.toUpperCase()+”;//不区分大小写
}).加入(‘and’);
const XPATH_BAD_TAGS=“//*[(名称空间-uri()!=”http://www.w3.org/1999/xhtml“)或(“+XPATH_PART_TAGS+”)”;
常量XPATH_BAD_ATTRIBUTES=“/@*[((名称空间-uri()!=”http://www.w3.org/1999/xhtml“)和(命名空间-uri()!=”)或(“+XPATH\u PART\u ATTRS+”)”;
常量XPATH_STYLE=“/@*[name()='STYLE']”;
/**
*检查内联样式定义是否安全
*
*@param{String}style属性的styleValue值
*@returnbool
*/
函数isStyleSecure(styleValue){
var styles=styleValue.split(“;”),
风格
名称、值、,
i、 l;
对于(i=0,l=styles.length;i
第一个想法是创建documentFragment,然后使用treeWalker或跟随dom树使用.firstChild等检查它的节点。但是我想这个解决方案是不安全的,因为它会让我打开所有注入的脚本。我说得对吗
还有别的办法吗 您需要的安全级别取决于您处理HTML的方式。如果您是通过电子邮件发送或在web服务器上显示它,那么您需要比仅对其进行文本分析更加小心 假设您在web服务器上显示此内容,这是一个非常困难的问题,您应该使用HTML净化器,例如和订阅安全更新,甚至可以找到自动获取更新的方法。为了获得额外的安全性,还可以使用iframe。如果你想逃避HTML,也要特别注意 当然,根据问题的实际情况,正确答案可能完全不同。以上应处理最常见的情况
另请参见所需的安全级别取决于处理HTML的方式。如果您是通过电子邮件发送或在web服务器上显示它,那么您需要比仅对其进行文本分析更加小心 假设您在web服务器上显示此内容,这是一个非常困难的问题,您应该使用HTML净化器,例如和订阅安全更新,甚至可以找到自动获取更新的方法。为了获得额外的安全性,还可以使用iframe。如果你想逃避HTML,也要特别注意 当然,根据问题的实际情况,正确答案可能完全不同。以上应处理最常见的情况
另请参见不要使用自己的消毒剂。使用一个由熟悉HTML、CSS和JS黑暗丑陋角落的人编写的文档
请参阅获取JavaScript消毒剂。不要使用自己的消毒剂。使用一个由熟悉HTML、CSS和JS黑暗丑陋角落的人编写的文档
请参阅以获取JavaScript净化剂。确保您在服务器端执行相同的操作……编写自己的HTML净化程序的问题是,大多数时候,人们试图清除有效的HTML,但浏览器设置为处理