从HTML标记清除所有内联事件

时间:2009-08-11 03:59:43

标签: html security xss sanitization

对于HTML输入,我想中和所有具有内联js的HTML元素(onclick =“..”,onmouseout =“..”等)。 我在想,编码以下字符是不够的? =,(,)

所以onclick =“location.href ='ggg.com'”
 会变成 onclick%3D“location.href%3D'ggg.com'”

我在这里缺少什么?

编辑:我确实需要接受有效的HTML(我无法逃脱它或实体是它)。

2 个答案:

答案 0 :(得分:2)

没有简单的方法来接受HTML,但不接受脚本。

您必须将HTML解析为DOM,删除DOM中的所有不需要的元素和属性并生成新的HTML。

<强> It can't be done reliably with regular expressions

on *属性不够。脚本可以嵌入stylesrchref和其他属性中。

如果您使用的是PHP,请使用HTML Purifier

答案 1 :(得分:0)

您可能有几个选项......最简单的方法是转换引号,可能还有&lt;&gt;字符,与HTML编码的等价物(“等),这将导致HTML代码按字面显示。

告诉我您使用的是哪种服务器端语言,如果您愿意,我可以为您指出更多特定于语言的信息。 (例如,PHP有htmlspecialchars()[1])。

编辑:我刚刚读了你的问题。好的,你想允许HTML通过但没有JavaScript吗?好吧,由于缺乏一个简单的解决方案,我建议只使用字符串替换(正则表达式,如果你可以,也许?)完全摆脱它们。

JavaScript中有一组有限的事件处理程序属性。认为需要引号并且你可能很好。

为了概念验证,在Perl中,你可能会做这样的事情:

$myInput =~ s/on(mouseover|mouseout|click|focus|blur|[...])(\"[^\"]*\")|(\'[^\']*\')\s*//gi;

因此,捕获事件处理程序名称(只包含其中的一部分),然后使用单引号或双引号引用表达式,在末尾有可选的空格,并用任何内容替换整个事物(即删除它)

但是,对于需要更高级别报价的内容,这不起作用,因为最终你会回到原始分隔符。原谅人为的,完全没用的例子:

onclick="eval('3+prompt("Enter a number: ")')"

在这种情况下,您可能希望编写一个循环,首先按字解析字符串(即查找事件处理程序名称),然后逐个字符地跟踪,随时跟踪引用级别的数量,跟踪当前分隔符:

  1. 标记处理程序名称开头的索引(onclick中的“o”等)
  2. 从引用级别0开始(或在处理开始引号分隔符后为1)。
  3. 如果当前分隔符是“并且您看到”,则将引用级别增加1并将当前分隔符切换为'。
  4. 如果当前分隔符是“并且您看到”,则将引用级别降低1并将当前分隔符切换为“。
  5. 如果当前分隔符是'并且您看到',则将引用级别增加1并将当前分隔符切换为'。
  6. 如果当前分隔符为'且您看到',则将引用级别降低1并将当前分隔符切换为'。
  7. 如果引用级别回到0,则表示字符串已结束。标记字符串结束的索引。
  8. 使用字符串操作函数从第一个索引到最后一个索引剪切子字符串。
  9. 它有点耗费时间,但理论上无论如何都应该有效,假设HTML格式正确。 (这是一个可怕的假设,但如果形态不好,你可以拒绝输入!)

    [1] http://us3.php.net/manual/en/function.htmlspecialchars.php