2

我正在开发一个 Web 框架,并试图在其中构建 XSS 预防。我已经对其进行了设置,因此它将转义传入的数据以存储在数据库中,但有时您希望保存用户生成的 html。我正在尝试制作一个自定义标签,以防止任何 javascript 执行,这是我的第一个 hack:

<html>
  <head>
    <script type="text/javascript" src="/js/jquery.min.js"></script>
  </head>
  <body>

    <preventjs>
      <div id="user-content-area">
        <!-- evil user content -->
          <p onclick="alert('evil stuff');">I'm not evil, promise.</p>
          <p onmouseover="alert('evil stuff');">Neither am I.</p> 
        <!-- end user content -->
      </div>
    </preventjs>

    <script type="text/javascript">
      // <preventjs> tags are supposed to prevent any javascript events
      // but this does not unbined DOM events
      $("preventjs").find("*").unbind();
    </script>

  </body>
</html>

我尝试使用 jQuery 取消绑定所有内容,但它不会取消绑定 DOM 中的事件,这正是我想要做的。是否可以取消绑定 DOM 元素的所有事件?

4

4 回答 4

4

您的问题是您这样做的目的是错误的——您应该在收到潜在恶意内容时过滤所有用户输入。

执行此操作时的第一条经验法则是“始终列入白名单,绝不列入黑名单”。与其在用户生成的 HTML 中允许任何和所有属性,不如简单地保留一个允许的属性列表并在收到 HTML 时删除所有其他属性(可能在客户端 - 肯定在服务器端。)

哦,HTML 不是常规语言。您需要使用 HTML 解析器,而不是该任务的正则表达式。

于 2011-08-25T19:35:59.377 回答
2

.unbind只会取消绑定使用 jQuery 附加的事件。您可以通过将它们设置为 null 来摆脱内联事件处理程序代码,例如:

$("preventjs *").removeAttr("onclick").removeAttr("onmouseover");

演示。

编辑:这是一个邪恶的解决方案,您可以删除以“on”开头的所有属性:

$("preventjs *").each(function() {
    var attribs = this.attributes;
    var that = this;
    $.each(attribs, function(i, attrib) {
        if(attrib.name.indexOf("on") === 0) {
            $(that).removeAttr(attrib.name);
        }
    });
});

演示。

于 2011-08-25T19:25:15.693 回答
1

问题是你有内联处理程序。unbind无法删除内联处理程序。

<p onclick="alert('evil stuff'...
   ^^^^

要删除内联处理程序,请使用removeAttr

$("preventjs").find("*").removeAttr('onclick');
$("preventjs").find("*").removeAttr('onmouseover');
于 2011-08-25T19:23:51.960 回答
0

您可以单独取消绑定事件:

$('p').each(function(){ this.onclick = this.onmouseover = undefined; });

如果要取消绑定其他事件,例如 mouseout,则必须将它们添加到该列表中:

$('p').each(function(){ this.onclick = 
                          this.onmouseover = 
                            this.onmouseout = undefined; });

当然你会想要使用除 之外的选择器$('p'),我只是不想放你的另一个,因为preventjs它不是 HTML 标签

于 2011-08-25T19:26:53.040 回答