我想出了一个使用jQuery来逃避HTML的黑客攻击,我想知道是否有人发现它有问题。
$('<i></i>').text(TEXT_TO_ESCAPE).html();
<i>
标签只是一个假人,因为jQuery需要一个容器来设置文本。
是否有更简单的方法可以做到这一点?请注意,我需要存储在变量中的文本,而不是用于显示(否则我只能调用elem.text(TEXT_TO_ESCAPE);
)。
谢谢!
答案 0 :(得分:62)
这是一种非常标准的方式,我的版本使用<div>
但是:
return $('<div/>').text(t).html();
虽然迈克塞缪尔指出,但这在技术上并非100%安全,但在实践中它可能非常安全。
当前的Prototype.js执行此操作:
function escapeHTML() {
return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
}
但它曾经使用“在div中放置文本并提取HTML”技巧。
还有_.escape
in Underscore,就像这样:
// List of HTML entities for escaping.
var htmlEscapes = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'/': '/'
};
// Regex containing the keys listed immediately above.
var htmlEscaper = /[&<>"'\/]/g;
// Escape a string for HTML interpolation.
_.escape = function(string) {
return ('' + string).replace(htmlEscaper, function(match) {
return htmlEscapes[match];
});
};
这与Prototype的方法几乎相同。我最近做的大多数JavaScript都有可用的Underscore,所以这些天我倾向于使用_.escape
。
答案 1 :(得分:11)
无法保证html()
将被完全转义,因此连接后结果可能不安全。
html()
基于innerHTML
,浏览器可以在不违反许多期望的情况下实施innerHTML
,以便$("<i></i>").text("1 <").html()
为"1 <"
,并且$("<i></i>").text("b>").html()
为"b>"
。
然后,如果你连接这两个单独安全的结果,你会得到"1 <b>"
,这显然不是两个明文片段串联的HTML版本。
因此,从第一原则中推导出这种方法并不安全,并且没有广泛遵循的innerHTML
规范(尽管HTML5确实解决了这个问题)。
检查它是否符合您要求的最佳方法是测试这样的角落情况。
答案 2 :(得分:1)
那应该有用。这基本上是Prototype.js库如何做到的,或者至少它是如何做到的。我通常会在三次调用“.replace()”时这样做,但这主要只是一种习惯。