The Attack of the Alerts and the Zombie Script (IE)

In our previous post we found a way to UXSS (bypass the SOP policy) using the htmlFile/ActiveXObject, however, I mentioned that there were other interesting things to do using that same object. Have you tried anything? If yes, congratulations. The only way to find bugs is by trying, and today we are going to explore another interesting thing that can be done with the same ActiveXObject.

Have you noted recently that all browsers have a feature to block perpetual alerts? As soon as you execute a second alert it comes with a check-box to disable the following ones, just like this:

This gives us (bad programmers) the chance to exit never ending alert-loops, but more important, it allows the user to defend himself against malicious pages that literally block the interface with fake messages. Users have now the chance to block all the following alerts by checking that box, but with the ActiveX window object we can continue throwing infinite alerts with no way to escape them.

If you haven’t read the previous post about the UXSS using htmlFile/ActiveXObject, please do it now. It’s important to understand why we are using specific members of this htmlFile/ActiveX (like how to get its window object). Anyway, let’s use the alert method from the ActiveXObject which completely bypasses the preference of the user of “no more alerts please!”. We can throw infinite ones but for this demo we will do it with just three.

doc = new ActiveXObject("htmlFile");
win = doc.Script; // win is the window object of the ActiveXObject
win.alert("Hello");
win.alert("2nd alert, no option to block me.");
win.alert("3rd alert, and still no way out!");

Honestly, I’m not impressed at all. Yeah yeah, unlimited alerts but it’s no big deal considering that other security researchers are bypassing DEP / CFG and re-enabling the God Mode. Let’s try something better. We will throw a few alerts but all visible at once, filling the entire screen with thousands them! No worries, in this PoC we will use just ten!

for (var i = 0; i < 10; i++)
{
   doc = new ActiveXObject("htmlFile");
   win = doc.Script; // win is the window object of the ActiveXObject
   win.setTimeout("alert('Hello, world!')", i * 100);
}

[ See the PoC Live on IE11 ]

Wow! This is not impressive, but it will keep the user and those amazing researchers busy . Click click click 🙂 . I know alerts are not interesting and let’s be honest, once the user has a chance to leave the page, he will be free from our horrible alerts, right? Wrong! We can be persistent and continue running our code even after he left our page. Imagine a user who goes to Google trying to escape from us, but continues to receive our alerts! Hehe 🙂 Let’s do it, it’s not hard at all.

 

Persistent Code

In order to make our code persistent (or a zombie script as some people call it), we need to keep a reference to the object that runs the script and make a call the window.open method. Those two things will make IE think it should not destroy the object because there’s still a reference to it. The good thing is that the reference can be in the object itself!

  1. Save a reference to the ActiveXObject.
  2. Use the window.open method.

Just one more thing: keep in mind that using the window.open method does not mean that we need to literally open a window/tab. In fact, we will use a very simple/old trick which apparently does nothing: window.open into the same window with an empty URL.

doc = new ActiveXObject("htmlFile");

// Alert every 5 seconds
doc.Script.setInterval("alert('Hello, world!')", 5000);

// Save a self-reference
doc.Script.doc = doc;

// Use the open method. Nothing changes here, but now IE will not
// destroy the previous reference and the script will continue running.
window.open("","_self"); // "Does nothing", but this line is crucial.

That’s it! Now the user can type anything in the address-bar, click on links or navigate as much as she wants, but our script will always be with her until the tab is closed. And by the way, everything here can be done straight from inside an iframe on a different domain, and still work (without bypassing SOP, of course).

[ See the PoC Live on IE11 ]

Wow! This is amazing! The setInterval keeps running even after leaving our page! Navigate, try it by yourself! Is there a way to combine the previous UXSS with this bug and have UXSS everywhere? Can we know where exactly the user is or the URL in the address bar? Check out this video where I was just teasing Eric because of a Twitter conversation that we were having.

Tip: the window.open trick that we did is useful for other things too. For example, if we run it against the top window (not matter how deeply framed we are), then, IE thinks the main window was opened with scripting and it allows us to close it without confirmations, just like this:

w = window.open("","_top"); // IE thinks the top was open with scripting
w.close();   // Now we can close it without confirmation

Have a nice day full of passion, bug hunter!

Manuel.