Hello fellow bug hunter! Today we are going back to Internet Explorer which despite getting old, tons people still use it. I am much happier with MSRC lately, they are really moving forward regarding Edge, design bugs, and they even extended its bug bounty, which seems to be permanent now.

All those are good news, but I still believe it is not acceptable to leave IE wide open. For example, right now all IE users can be turned into bots with the zombie script bug (which has been public and unpatched for months). If you don’t think it’s important, then imagine what black hats can do right now: they can stay in your browser even if you navigate to a different site, which gives them plenty of time to do ugly stuff like mining digital currencies while abusing of users CPUs. Also, IE has its popUp blocker is completely broken and nobody seem to care. Fine, but I think these things should be patched or at least set a big red warning to IE users when they open it, something like “We do not support this browser anymore, use Microsoft Edge“.

In my opinion, Microsoft is trying to get rid of IE without saying it. It would be easier, more honest to simply tell users that their older browser is not being serviced like Edge. Current browser stats, according to Netmarketshare show that IE is still more popular than Edge: 17% vs 6%.

I firmly believe that IE should be treated like Edge in terms of security, otherwise get rid of it completely. Either way, let’s explore another bug on IE that allows attackers to know the address where the user is going. Mind reading? Nope, we know mind reading does not exist, but take a look and see how IE allows us attackers to do what appears to be magic.

Abstract

When a script is executed inside an object-html tag, the location object will get confused and return the main location instead of its own. To be precise, it will return the text written in the address bar so whatever the user types there will be accessible by the attacker. In a hurry? Take a look at the video and watch how we read what the user types inside IE address-bar!

Objects and Document Modes

Object tags behave differently depending on the documentMode where they are being rendered. For example, if we add the compatibility meta tag at the beginning of a page it will look and behave like an iframe but it will think it is the top window.

<head> <!-- COMPATIBILITY META TAG --> <meta http-equiv="X-UA-Compatible" content="IE=8" /> </head> <object data="obj.html" type="text/html"></object> 1 2 3 4 5 6 7 <head> <!-- COMPATIBILITY META TAG --> <meta http-equiv = "X-UA-Compatible" content = "IE=8" /> </head> <object data = "obj.html" type = "text/html" > </object>

In the code above, “obj.html” is rendered inside the object and the contents are wrapped inside a block similar to an iframe, however, comparing its window object with the top one returns true, when it shouldn’t: it is not the top window. Take a look at the code executed inside the object tag: it thinks window == top, which isn’t really true.

Our object believes it’s the top window, to the point that other members like frameElement return always null, a behavior that only happens on top windows (on IE).

Let’s try the same code without the compatibility tag. It seems that the object now understands its place in the universe and behaves like an iframe.

<!-- COMPATIBILITY META TAG REMOVED --> <object data="obj.html" type="text/html"></object> 1 2 3 4 <!-- COMPATIBILITY META TAG REMOVED --> <object data = "obj.html" type = "text/html" > </object>

Essentially, the object is being rendered as an independent entity in older document modes but as an iframe in newer ones. Regardless of that, internally both are WebBrowser controls, Trident engines exposing the same members.

Inherited window members

Let’s set back an older documentMode and find a way to exploit this confusion-bug which does not seem to be that bad because cross-domain restrictions are still in place, and the X-FRAME-OPTIONS header works perfectly well. There are members like window.name which are inherited by the object (the object inherits the name of its parent) but that’s not super-bad except for specific advertising technologies which insecurely use the window.name to pass information across iframes.

Having said that, there’s at least one inherited object that really causes trouble: location. Inside an object tag, location.href will return the location of the main (top) window. The code below renders the object with its source pointing to object_location.html, but when we retrieve its location it returns the top instead.

Again, this confusion-bug is not useful because we are still on the same domain. Even if we can retrieve -thanks to the confusion- the location of the top, as long as we are on the same domain things are not exciting. By the way bug hunter, I tried for a few minutes to change the location of the object, but no success. If you want to research on this area I would suggest going deeper because I believe it should be possible. Regardless of that, while trying to achieve a UXSS (persistence is key for everything in life) an interesting bug stumbled upon me: when the object is injected onbeforeunload what we get is not the top location anymore, but the location that the browser is going to or, what’s currently written into the address bar.

In other words, if we retrieve the location.href of the object while the user is leaving the main page, we will be able to know what was typed into the address-bar, or, if the user clicked on a link we will know the address of the link that the browser is going to.

For our testing purposes, we will just interrupt the loading of the new site and show the URL to the user. Of course, an attacker would simply post-back the address and load the site anyway making this transparent to the user. Let’s do a simple document.write of the object while the user is leaving.

window.onbeforeunload = function() { document.write('<object data="loc.html" type="text/html" width="800" height="300"></object>'); document.close(); } 1 2 3 4 5 6 7 window . onbeforeunload = function ( ) { document . write ( '<object data="loc.html" type="text/html" width="800" height="300"></object>' ) ; document . close ( ) ; }

And read the location at that precise moment (onbeforeunload).

document.write("Let me read your mind. You wanted to go here: " + location.href +); 1 2 3 document . write ( "Let me read your mind. You wanted to go here: " + location . href + ) ;

That’s it! Now we will retrieve the object location when the user is leaving and know exactly what she typed into the address bar. It does not have to be a full URL, for example, if the user types words into the address bar, it will automatically be converted to a search query URL (Bing by default on IE) which can of course be completely read!

Have a nice day, and keep pushing into this object! I’m sure there are tons of things to be discovered.

Manuel.