Monthly Archives: January 2011
JavaScript ( (__ = !$ + $)[+$] + ({} + $)[_/_] +({} + $)[_/_] )
First off credit where credit is due.
Update 1: Well hello reddit and hackernews.
1) I didn’t write this JavaScript.
2) I didn’t find this JavaScript.
I saw it in a slide deck from BlackHat DC 2011. Called XSS Street-Fight. Most of the presentation was dry JavaScript /mod_security, but this caught my eye.
($=[$=[]][(__=!$+$)[_=-~-~-~$]+({}+$)[_/_]+
($$=($_=!”+$)[_/_]+$_[+$])])()[__[_/_]+__
[_+~$]+$_[_]+$$](_/_)
Care to guess what that does?
How about if I type it like this.
($=[$=[]][(__=!$+$)[_=-~-~-~$]+({}+$)[_/_]+
($$=($_=!”+$)[_/_]+$_[+$])])()[__[_/_]+__
[_+~$]+$_[_]+$$](document.cookie)
That’s right this is an alert() if it lands anywhere in
an executable section of JavaScript/dom it pops up the cookie.
Go ahead and put it in a script tag in your browser it will pop up a “1”
That’s when I couldn’t put this down.
First there are really two lines here.
($ = [ $=[]] [ (__ = !$ + $ )[ _ = -~-~-~$] + ({} + $)[_/_] + ( $$ = (
$_ = !” + $)[_/_] + $_[+$] ) ] )()
becomes sort()
[__[_/_]+__[_+~$]+$_[_]+$$](_/_)
becomes alert(1)
Let’s start to tear this apart.
$=[] is a blank array
$=[$=[]] is an array with a reference to an array.
So $ derefs to the value 0.
Now we have a 0 we can freely reference.
__ = “false”via (__ = !$ + $ )
_ = -~-~-~$
(The ~ operator in JavaScript means -(N+1) so -~ = +1
if $ = 0 then -~-~-~$ = 3
_ = 3
thus _/_ = 3/3 = 1
(__ = !$ + $ )[ _ = -~-~-~$]
(“false”)[_]
(“false”)[3]
“false”[3] = s
({} + $)[_/_]
(” object”)[_/_]
(” object”)[1]
” object”[1] = o
$$ = ( $_ = !” + $)[_/_]
$$ = ( “true”)[1]
“true”[1] = r
$_[+$] = “true”[0] = t
$_ = “true”null
$$ = rt via
($$ = ( $_ = !” + $)[_/_] + $_[+$] ))
!” = “true”
$_ = (true)
$_[1] = r
$_[0] = t
$$ = rt
Thus the first line becomes sort()
($ = [ $=[]] [“s” + “o”+ “r”+ “t” ] )()
Sort takes a function as it’s parameter to
execute thus firing the second line. It turns out this assumption was wrong on my first go. Scroll to the bottom for the updated explanation I quote from Benjaminsen .
[__[_/_]+__[_+~$]+$_[_]+$$](_/_)
$ = 0
_ = 3
__ = “false”
$_ = “true”
$$ = “rt”
[__[_/_]+__[_+~$]+$_[_]+$$](_/_)
becomes
[__[1] + __[3 + -1] + $_[3] + $$)(1);
becomes
[“false”[1] + “false”[3 + -1 ] + “true”[3] + “rt”] (1)
[ a + l + e + r + t ](1)
alert(1)
From Benjaminsen @ reddit.
“
($=[]["sort"])()["alert"](1)
We can further break that into
a = [] // Create array
b = a["sort"] // Get reference to sort method
c = b() // Execute sort outside the context of an array to return a reference to window
d = c["alert"] // Get reference to window.alert
d(1) // Execute window.alert with the argument 1
So what happens is
window["alert"](1)
not
[1,2].sort(alert)
“
Enjoy!