Javascript Use of Window Object through alternate means

cross-browserdomjavascript

Disregard your usual paradigms for a mere moment here….

I've seen a few sites who have used the following logic:

a=[];
b=a["sort"];
c=(b)();
c["alert"](1); // intended output: Alert displaying "1"...

supposedly to access (I'm guessing here) the primitive of the sort function to gain access to the window object, and then using that to access "alert"…

I've tried executing this ages ago, and it worked a charm… But some twelve months or so later, I tried to run it again… and it's failed to execute, and given the following error:

TypeError: can't convert undefined to object

My question is, why wouldn't this logic work? It seems quite sound… Or is it?

And yes, I know that I could just do alert(1) and be done with it, but I'm trying to get an understanding of alternate ways of coding… I work in IT security and I know certain people have ways of using XSS to find alternative ways to perform generic functions to compromise systems…

Best Answer

I'm not sure why it wouldn't work in a given environment but it works in a Chrome console.

Let's walk through it:

a=[];

a is defined without a var declaration so it implicitly becomes a member of the global object which in browsers is the window object. This wouldn't work in strict mode (look for 'use strict'; - could be double-quoted), which would throw an error rather than do the implicit global thing, which yes, is one of few JS design warts that I actually agree was a bad idea with no redeeming qualities whatsoever. But strict mode will defeat the whole thing right here.

b=a["sort"];
//b=a.sort; // to make it even more clear. bracket notation is for obfuscation purposes

We assign the sort method of arrays to the var b. Called as b(), it's no longer called as a property/method of the array.

c=(b)();
//c=b(); // no need for (b) since b is already an evaluated function you can call

So, b is the array method sort but now it's just a loose function. What does that generic func do? It takes the function it's passed as an arg to sort whatever is represented by the 'this' keyword, sorts it in place and then returns 'this'. Since b is now just a loose function, 'this' should be the window object. In order to break at this point, passing undefined would have to break the sort method (which might make the most sense given your error) or the sort method would have to be behaving as if it had been permanently applied to Array.prototype as if the function bind method had been used (see "bind" on MDN).

Note: I use words like "seem" because sort returns as a [native code] method in Chrome which means it could be doing all kinds of things in the details as long as it technically fulfills ECMA spec which all browser vendors have been taking seriously since IE5.

c["alert"](1); // intended output: Alert displaying "1"...
//c.alert(1); //works too.
//alert(1); //and yes the same exact thing but easier to obfuscate from the top one

At this point, nothing magic is happening. We have the global object. We fire alert from it as a property of the global object.

Related Topic