简体   繁体   中英

javascript unbind dom events

I'm working on a web framework and am trying to build XSS prevention into it. I have set it up so it will escape incoming data for storage in the database, but sometimes you want to save html that the user generates. I am trying to make a custom tag that will prevent any javascript from executing, here is my first hack at it:

<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>

I tried using jQuery to unbind everything, but it doesn't unbind events in the DOM, which is exactly what I'm trying to do. Is it possible to unbind all events for a DOM element?

You're problem is that you are doing this on the wrong end of things -- you should be filtering all user input of potentially hostile content when you receive it .

The first rule of thumb when doing this is "always whitelist, never blacklist". Rather than allowing any and all attributes in your user-generated HTML, simply keep a list of allowed attributes and strip away all others when you receive the HTML (possibly on the client side -- definitely on the server side.)

Oh, and HTML is not a regular language. You'll want to use an HTML parser, not a regular expression for this task.

.unbind will only unbind events attached using jQuery. You can get rid of inline event handler code by setting them to null, eg:

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

Demo.

EDIT: Here's an evil solution, you can remove all attributes starting with "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);
        }
    });
});

Demo.

The problem is that you've inline handlers. unbind cannot remove inline handlers.

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

To remove inline handlers, use removeAttr

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

You can unbind the events individually:

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

If you want to unbind other events like mouseout you have to add them to that list:

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

Of course you'll want to use a selector other than $('p') , I just didn't want to put your other one because preventjs is not an HTML tag

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM