添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
稳重的啤酒  ·  Missing XSS flaws ...·  3 周前    · 
聪明的茶叶  ·  jQuery set ...·  3 周前    · 
潇洒的硬币  ·  Using innerHTML ...·  3 周前    · 
文雅的沙滩裤  ·  Internet Explorer, ...·  3 周前    · 
淡定的板凳  ·  VC与JavaScript交互(三) ...·  1 年前    · 
粗眉毛的创口贴  ·  jxl ...·  1 年前    · 
温暖的梨子  ·  We need your consent·  1 年前    · 

I have come across a weird situation which looks like a security bug in IE. This concerns DOM manipulation by creating new objects using innerHTML.

Some background on the topic: In a certain project, I am using a 3rd party WYSIWYG Html rich editor. As all of these editors, they create new DOM elements (mainly fancy toolbars with buttons). After development, the application was installed on some QA machines and servers. Much to my surprise, when browsing to the application from the actual server itself (i.e. localhost), in IE all the scripting worked well, except for the rich editor. The editor’s html was built successfully, but the toolbar buttons were inactive.

I spent some time investigating this. If no scripting was allowed what so ever, the entire website wouldn’t have functioned at all, and the editor wouldn’t have shown up – this wasn’t the case. JavaScript was clearly working everywhere except for those toolbar buttons. Testing with NOSCRIPT tag also failed (i.e. JavaScript is enabled). I checked the Security zones under IE and found the following: In Local Intranet the Active Scripting settings was set to Enabled, but in the Internet Security zone it was set to Disabled. I tried to set it to Enabled, although I was absolutely certain that there was nothing in the web application nor in the rich editor that was using the Internet zone, and behold – the buttons started to work after refreshing the page!

Turns out that something the rich editor was doing was considered by IE to be in the Internet zone, or so it  seems, and therefore the button events did not work. I debugged this more and more till I found the actual innerHTML JavaScript command which the editor’s code used in order to build the editor’s DOM elements, and nothing seemed wrong. Debugging that same code also provided no errors in the Console window, and nothing hinted at this problem. But when I reproduced this by disabling the Active Scripting settings in the Internet zone again, the buttons were inactive again.

So, I created my own sample and added DOM elements using innerHTML, in a similar fashion to how the rich editor added it’s own buttons, in order to try to emulate and understand what was going on here. I enabled Active Scripting settings both in the Internet zone and in the Local Intranet zone. The following works as expected:

Note (below) the Security zone of the page (in the IE browser window, right click and select Properties for this dialog to come up). As you can clearly see in the screenshot, IE recognizes that the browsed page is in the Local Intranet zone (note the ‘localhost’ in the address bar). This means that local JavaScript code runs great, where as non-local JavaScript code is disabled (for example, if we switch to jQuery on the CDN instead of my local jQuery js file, jQuery won’t work. That is why I had to download jQuery and use it locally in this example).

In order to reproduce this bug, we’ll disable Active Scripting on the Internet zone, and leave it as enabled for the Local Intranet zone. Here’s the Internet zone:

The Local Intranet remains as Enabled:

Now we’ll refresh the page. While the ‘go’ is rendered properly on the browser, it is now inactive, despite the fact that the entire page is running only local JavaScript code. Although I can clearly see the “onclick” event in the Debugger Tools on the newly created anchor – it is not working. No error message was thrown, and no message was shown in the Console windows of the Debugging Tools. I could not find any documentation about this behavior in Microsoft’s different sites (but it does not mean that there isn’t any).

Workaround

At this stage I was puzzled about my next move. I had to try and think of a workaround for this, or I’ll risk having an HTML editor which is non functional in this scenario, with no way to warn the user and explain how to change this settings (NOSCRIPT isn’t working here so there really isn’t a way to tell using JavaScript). This situation is not necessarily uncommon: on some Windows server installations it looks like by default IE is configured to disable Active Scripting on the Internet Security zone. So potentially DOM elements created by local JavaScripts may be malfunctioning. I attempted several workarounds using jQuery to “re-attach” events. This worked, but I had trouble to figure out when to perform the workaround or risk the event occurring twice , in case Active Scripting is enabled. After experimenting some more, I noticed that there are times in which innerHTML code which included events does work . Finally I understood the following “rule”: if innerHTML is set on an element which is already a part of the DOM tree, the events work properly. If the innerHTML is set on an element which is not yet a part of the DOM (i.e. new element which was just created), and only then the element is added to the DOM – the event does not work! Note the following change in the code:

As you can see, by switching lines 12 and 13, I added the wrapping div to the DOM tree first, and only then I set the innerHTML property to an anchor with an “onclick” event. I refreshed the page and now the event worked as expected! It’s as if IE creates the elements well but the events are not triggered, if the newly created element is not yet attached to the DOM. Appending the element afterwards is simply “too late”. Note, that if I had set the innerHTML of the #container div directly (i.e. without creating a second div), this would have worked as #container div is already a part of the DOM.

The same behavior goes for jQuery Insertion – the following ‘append’ creates the elements successfully, but the ‘onclick’ does not work (jQuery 1.7.1):

I assume that jQuery first creates an element and sets it’s innerHTML, prior to attaching it to the DOM. So the same behavior applies. The workaround is very easy:

As you can see, jQuery’s ‘html’ works on an existing DOM element (‘#container’) and that is why the event works, whereas ‘append’ seems to create a new DOM element and set it’s innerHTML before the element is attached to the DOM, and that is why it fails.

“Armed with this knowledge”, the workaround on how to solve the non-working buttons of the Html editor is now very simple, and applies to both enabled and disabled Active Scripting scenarios; all that is required, is to “re-apply” the innerHTML property of the newly created elements. Because those new elements are now a part of the DOM, setting the innerHTML recreates the child elements and their events correctly this time. I used jQuery for setting the innerHTML. For example:

  • Lines 11-14 simulate code which creates the html in a buggy manner.
  • Line 17 applies this workaround for IE only.
  • Line 18 takes the DOM’s html from the newly created div element.
  • Line 19 “re-applies” the html, which basically means that the anchor tag and the ‘onclick’ are recreated.
  • This time IE handles the ‘onclick’ well:

    Summary

    I believe that the described behavior is an IE bug. If MS wanted to block element creation using innerHTML when Internet zone Active Scripting is disabled, it would have blocked it entirely disallowing the above workaround. Fortunately, this bug is easy to workaround once you realize what it is. Naturally, this workaround could prove to be expensive, so I would limit using it only to specific cases where you have no alternative, and only for IE (like I had when using the 3rd party editor).

    Follow up

    This bug was reported to MS and also to the jQuery bug tracker .