BOOK THIS SPACE FOR AD
ARTICLE ADSo I wanted to try this payload first and see if it worked and also find out how it worked! And therefore I opened the browser console and tried this trick that Gareth mentioned. And it worked (it had to, ofcourse!)
So now I started poking around with this and see if I can make some sense out of it!
So first off, let’s keep it simple and see how we can pop alert using the __proto__ property:
__proto__.constructor.constructor(“alert(1)”)()
The __proto__.constructor.constructor results in the Function constructor which allows you to generate a function from a string and therefore execute arbitrary code, like we did for the alert in this case!
Now let’s see Gareth’s payloads:
Payload #1 which supposedly fails:
__lookupGetter__(‘__proto__’)
and
Payload #2 which successfully leads to an alert:
[__lookupGetter__][0](‘__proto__’).constructor(‘alert(1)’)()
So my first thought was what is this array doing. Did it changed the __lookupGetter__ method?
So I tried to check if the __proto__ property and the function:
Indeed they were different! I initially thought I found the difference, but that didn’t gave me the reason...
So I tried a bit more — trying to print the prototype chain to see for any differences and check the available functions etc.
All that lead to a dead-end! And then I checked the tweet back again and found that @TomNomNom just did a simple console.log to see what the difference was:
Did you see?! this got bound to the Array!
And that array contains the reference to the function fun()!
So, in the payload Gareth posted, the trick was — this pointed to Window object initially now points to the array object containing the reference to the window and all its methods and that’s what got the whole thing working!
@TomNomNom pointed out that this things was same as:
Which is brilliant right! Same technique as we saw with the Array — this got changed from Window to the object we just declared and thus all the window object properties are inside this new object that this points to!
Gareth then pointed to amazing payloads:
({f: valueOf}).f()
this.valueOf() shows the value of the current object:
And
({f: toString}).f()
Since this got changed, notice the output difference!