使用正则表达式进行标记并没有错。但是使用正则表达式制作一个完整的 HTML 标记器需要大量的工作并且很难做到正确。我建议使用适当的解析器,因为您可能需要删除脚本标签等。
假设不需要完整的标记器,可以使用以下正则表达式和代码从 HTML 标记中删除 on* 属性。
因为没有使用适当的分词器,所以即使在脚本、cmets、CDATA 等中,它也会匹配看起来像标签的字符串。
不能保证所有输入/浏览器组合的所有事件属性都会被删除!请参阅下面的注释。
容错注意事项:
浏览器通常会容忍错误。
因此,当存在“无效”数据时,很难标记化标签并获取属性,因为浏览器会看到它们。
由于浏览器之间的容错和处理方式不同,因此不可能制定出适用于所有情况的解决方案。
因此:某些浏览器(当前、过去或将来的版本)可以将我的代码认为不是标签的东西视为标签,并执行 JS 代码。
在我的代码中,我试图模仿最近 Google Chrome 版本的标签(和容错/处理)的标记化。
Firefox 似乎也是这样做的。
IE 7 有所不同,在某些情况下它不那么宽容(这比它更宽容的情况要好)。
(IE 6 - 让我们不要去那里。见XSS Filter Evasion Cheat Sheet)
相关链接:
代码
$redefs = '(?(DEFINE)
(?<tagname> [a-z][^\s>/]*+ )
(?<attname> [^\s>/][^\s=>/]*+ ) # first char can be pretty much anything, including =
(?<attval> (?>
"[^"]*+" |
\'[^\']*+\' |
[^\s>]*+ # unquoted values can contain quotes, = and /
)
)
(?<attrib> (?&attname)
(?: \s*+
= \s*+
(?&attval)
)?+
)
(?<crap> [^\s>] ) # most crap inside tag is ignored, will eat the last / in self closing tags
(?<tag> <(?&tagname)
(?: \s*+ # spaces between attributes not required: <b/foo=">"style=color:red>bold red text</b>
(?>
(?&attrib) | # order matters
(?&crap) # if not an attribute, eat the crap
)
)*+
\s*+ /?+
\s*+ >
)
)';
// removes onanything attributes from all matched HTML tags
function remove_event_attributes($html){
global $redefs;
$re = '(?&tag)' . $redefs;
return preg_replace("~$re~xie", 'remove_event_attributes_from_tag("$0")', $html);
}
// removes onanything attributes from a single opening tag
function remove_event_attributes_from_tag($tag){
global $redefs;
$re = '( ^ <(?&tagname) ) | \G \s*+ (?> ((?&attrib)) | ((?&crap)) )' . $redefs;
return preg_replace("~$re~xie", '"$1$3"? "$0": (preg_match("/^on/i", "$2")? " ": "$0")', $tag);
}
示例用法
Online example:
$str = '
<button onclick="..javascript instruction..">
<button onclick="..javascript instruction.." value="..">
<button onclick=..javascript_instruction..>
<button onclick=..javascript_instruction.. value>
<hello word "" ontest = "hai"x="y"onfoo=bar/baz />
';
echo $str . "\n----------------------\n";
echo remove_event_attributes($str);
输出:
<button onclick="..javascript instruction..">
<button onclick="..javascript instruction.." value="..">
<button onclick=..javascript_instruction..>
<button onclick=..javascript_instruction.. value>
<hello word "" ontest = "hai"x="y"onfoo=bar/baz />
----------------------
<button >
<button value="..">
<button >
<button value>
<hello word "" x="y" />