I am interested in understanding the internals of JavaScript. I’ve tried to read the source for SpiderMonkey and Rhino but it’s quite complex to wrap my head around.
The reason I ask is: why does something like
(![]+[])[+!![]+[]]produce"a"(Å=[],[µ=!Å+Å][µ[È=++Å+Å+Å]+({}+Å)[Ç=!!Å+µ,ª=Ç[Å]+Ç[+!Å],Å]+ª])()[µ[Å]+µ[Å+Å]+Ç[È]+ª](Å)producealert(1)?
Source: http://sla.ckers.org/forum/read.php?24,32930,page=1.
There’s many more examples of JavaScript oddities on that forum and I wanted to know how it works from a programming point of view with respect to web application security.
Why does
(![]+[])[+!![]+[]]produce “a”step by step: this is parsed in:
(![]+[])and[+!![]+[]]. First bit was already explained by artemb:[]is an array. Negating it,![]evaluates to a boolean,false– that’s just how!works when it is applied to something that is notnullor undefined. Again as pointed out by artemb, appending this+[]forces the boolean to be converted to a string. That’s because the+is a string concatenation operator. The booleanfalseis then converted to its string representation,"false".Then, the second bit,
[+!![]+[]]. First of all, the outer[and]serve to treat the preceding string, which we just dervived is equal to"false"as an array of characters. By putting an integer index inside the[and], you get the character at a particular index. So what remains is+!![]+[]This consists of 4 pieces:
+,!![],+and[]. First!![]is evaluated. We already saw that![]is a booleanfalseso prepending another!negates it, and yieldstrue. Next thing what happens is that the+in+!![]gets applied, and by applying+it converts the booleantrueinto the number representation, which is1(so+trueis1) The+[]that follows makes a string again from that1yielding"1"but it does not really make sense, the shorter expression(![]+[])[+!![]]already producesa. Appending+[]doesn’t hurt either, the resulting expression is simply["1"]instead of[1]. My hunch is that when[]is applied to an array, whatever is inside the[]will be coerced into a number, which for"1"would give1again. So either way,+!![]+[]evaluates to1, making the final expression:"false"[1]which is saying: gimme the character at index 1 from the string"false", and since by default, arrays start at0in javascript, this is the second character of"false", anda.