
JavaScript ( (__ = $ + $)[+$] + ({} + $)[_/_] +({} + $)[_/_] ) - there
http://adamcecc.blogspot.com/2011/01/javascript.html
======
paulirish
Here's a converter from regular JS to using a subset of these characters:
[http://discogscounter.getfreehosting.co.uk/js-
noalnum_com.ph...](http://discogscounter.getfreehosting.co.uk/js-
noalnum_com.php)

And the forum thread where this technique was explored at length:
<http://sla.ckers.org/forum/read.php?24,33349,33405>

Superfun. :D

~~~
citrus
"jjencode" generates more short code: <http://utf-8.jp/public/jjencode.html>

And "aaencode" Encode any JavaScript program to emoticons:
<http://utf-8.jp/public/aaencode.html>

------
bobds
This is pretty cool. Reminds me of a Defcon presentation that only used
whitespace characters to encode the script (and a bit of boilerplate). I think
it looks less suspicious than lots of symbols lumped together.

Here it is: [https://www.defcon.org/html/links/dc-
archives/dc-16-archive....](https://www.defcon.org/html/links/dc-
archives/dc-16-archive.html#Kolisar)

[https://www.defcon.org/images/defcon-16/dc16-presentations/d...](https://www.defcon.org/images/defcon-16/dc16-presentations/defcon-16-kolisar.pdf)

------
verysimple
For those like me who stumble upon this type of js expressions for the first
time and are scratching their heads, John Resig (of jQuery fame) attempted
some basic explanations in this old HN post:

<http://news.ycombinator.com/item?id=1154338>

------
loganlinn
Great use of JavaScript's weird + operator.

The whole trick stems from the fact that !$ == false and !$+$ == "false"

~~~
hencq
Wow, I knew the + operator was weird, but didn't realise it allowed you to do
stuff like that.

What I don't get though, wouldn't you still need to call eval() on it to do
anything with it? Or does javascript do a 'implied eval' when you try to call
a string?

~~~
hencq
Ah found the answer to my own question in the reddit thread about the same
thing: <http://www.reddit.com/r/programming/comments/f6xto/_/c1dr729>

~~~
joakin
This is what is missing in the article, thank you

------
blago
I'm missing the purpose. Can someone explain?

~~~
jrockway
Some people think that they can secure their sites against XSS by regexing all
the "bad JavaScript" out. If the "security software" sees "document.cookie",
then it stops the script from executing. (Or it just replaces it with the
empty string, etc.)

Problem is, there are a lot of ways to say document.cookie, and a blacklist is
going to miss one of them.

Moral of the story: if people can execute scripts on your page, you're 0wned.
Everyone competent knows this, but sometimes the less competent are slow to
realize this.

So, the script that the article describes is for their benefit. Good luck
writing a regex to stop this one...

(There are also even simpler "exploits", if you regex document.cookie to the
empty string, then "document.document.cookiecookie" regexes to
"document.cookie". Ooops.)

~~~
patrickaljord
> Problem is, there are a lot of ways to say document.cookie

Could you give an example?

~~~
JeremyBanks
Using the converter linked above[1] I can convert

    
    
        alert(document.cookie)
    

to the equivalent

    
    
        ([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()[(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]])(([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()[([][[]]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[+[]]+((+[])[([][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]])[([][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+[][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()[(![]+[])[+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()+[])[!+[]+!+[]]]((![]+[])[+!+[]]+[+[]])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(!![]+[])[!+[]+!+[]+!+[]]])
    
    
    
        [1] http://news.ycombinator.com/item?id=2129815

~~~
sirrocco
How would you protect against that ? is encoding the output enough ?

~~~
Xk
Sanitize both input and output. Make sure everything outputted is encoded. <
to &gt; > to &lt;, " to &quote;, etc. As long as all they can write is normal
characters then you're safe [1].

[1] Or rather, safer. There are always obscure ways to get around almost
everything. So you really have to take care to exactly the situation you're in
at the moment.

~~~
codingthewheel
Sanitize everything, use multiple redundant sanitizer libraries (there are
several out there that handle different things), and use a whitelist, rather
than a blacklist, based approach. If you want to allow the use of <a> tags,
enforce that they adhere to the exact format of a safe <a> tag, otherwise
encode or strip them. One look at the XSS cheatsheet page should be enough to
convince any sane developer of the futility of a blacklist-based approach.

------
messel
The perfect gag gift for a new dev team member. "this is an example of our
coding style"

~~~
Natsu
Is it bad that I first tried to interpret it as Perl, even though it was
clearly labeled as JavaScript?

------
perssontm
If all those blackhat-efforts could be put to better use somewhere.. although
its fascinating what _can_ be done. They are truly creative in their own way.
:)

------
wmwong
I'm a little confused. It seems like he didn't need to call the sort function
in order to call the alert function. Is this correct? He could have built the
alert call in the same manner and just call it by itself. I assume the sort
function was thrown in there for a larger example?

~~~
bradshaw1965
The reddit link in the post right above yours explains that sort is used to
get a reference to the "window" object since sort returns "this" and by
assigning it to a variable it returns the default context which in this case
is "window".

------
gbog
Searching for this string on Google, as I have no access to blogspot, I fell
down on ​<http://asdfg.jodi.org> (js art, NSFW and may kill your browser). It
is related, somewhat.

------
xtacy
I saw these long back in a forum that listed such expressions for all
printable characters; I am unable to locate them now. Can someone help?
Thanks!

~~~
noibl
See Paul Irish's comment:
[http://adamcecc.blogspot.com/2011/01/javascript.html?showCom...](http://adamcecc.blogspot.com/2011/01/javascript.html?showComment=1295666584419#c4861796849333913434)

------
michaelty
I wonder if you could use this in an interview...

~~~
weixiyen
This is great idea, if your goal is to not hire anyone.

~~~
bl4k
except HN readers

~~~
gokhan
How many of them can understand this?

~~~
jonursenbach
Before or after this article was posted?

------
ohashi
This post makes me feel dumb. :(

------
nicksergeant
Well, that was interesting.

------
gcb
why he needed $=[$=[]] and not just $=[[]]

~~~
tlrobinson
The second $ (which is actually the first assignment) was used as as an alias
to [] before the first $ gets assigned. I guess to reduce the number of
characters.

~~~
gcb
it actually increases the number of chars.

inner $=[] will be overwritten by outer $=[$], which is the same as $=[[]]

or am i missing something?

~~~
tlrobinson
It doesn't get overwritten until the rest of the expression has been
evaluated, thus $ == [] for all the uses of $ within the expression.

~~~
gcb
still not clear.

the code unobfuscated is: (a=[a=[]]['sort'])()['alert'](1)

my argument is that this is the same, and less chars
(a=[]['sort'])()['alert'](1)

I can't see any benefit of the encapsulation of the array assignment there.

edit: also, just noticed that my previous comments i was writting $=[[]] when
i was thinking of $=[], but both works the same, and are still less chars :)

~~~
tlrobinson
Ok here's the best I can do:

(lines are numbered in order of execution, with explanations of each line)

    
    
        ($=[                // 14: $ = Array.prototype.sort ([]["sort"] = Array.prototype.sort)
            $=[]            // 1: $ = []
        ][
            (__= !$+$ )[    // 2: __= "false" (![]+[] = false+[] = "false")
                _=-~-~-~$   // 3: _= 3 (-~-~-~[] = -~-~-(-1) = -~-~(1) = -~-(-2) = -~(2) = -(-3) = 3)
            ]+              // 4: "s" ("false[3]" = "s")
            ({}+$)[         // 5: "[object Object]" ({}+[] = "[object Object]")
                _/_         // 6: 1 (3/3 = 1)
            ]+              // 7: "o" ("[object Object]"[1] = "o")
            ($$=            // 12: $$ = "rt"
                ($_=        // 9: $_ = "true"
                    !''+$   // 8: "true" (!''+[] = true+[] = "true")
                )[_/_]+     // 10: "r" ("true"[3/3] = "true"[1] = "r")
                $_[+$]      // 11: "t" ("true"[+[]] = "true"[0] = "t")
            )               // 13: "rt"
        ])()[               // 15: window (sort() = window)
            __[_/_]+        // 16: "a" ("false"[3/3] = "false[1]" = "a")
            __[_+~$]+       // 17: "l" ("false"[3+(~$)] = "false"[3+(-1)] = "false"[2] = "l")
            $_[_]+          // 18: "e" ("true"[3] = "e")
            $$              // 19: "rt"
        ](_/_)              // 20: alert(1) (window["alert"](3/3) = alert(1))
    

[] is assigned to "$" in step one. Several of the steps between 2 and 11
reference "$" to save one character rather than typing

If you wanted to remove the a=[] you'd have to include a bunch of "[]"s
inline, e.x.:

    
    
        ($=[][
            (__= ![]+[] )[
                _=-~-~-~[]
            ]+
            ({}+[])[
                _/_
            ]+
            ($$=
                ($_=
                    !''+[]
                )[_/_]+
                $_[+[]]
            )
        ])()[
            __[_/_]+
            __[_+~$]+
            $_[_]+
            $$
        ](_/_)
    

Replacing the no-alpha variable names with letters might help:

    
    
        (F=[
            A=[]
        ][
            (B= !A+A )[
                C=-~-~-~A
            ]+
            ({}+A)[
                C/C
            ]+
            (D=
                (E=
                    !''+A
                )[C/C]+
                E[+A]
            )
        ])()[
            B[C/C]+
            B[C+~F]+
            E[C]+
            D
        ](C/C)
    

Notice both "A" and "F" were "$". The original code reused "$" to save a
character.

I'm not sure I can make it any clearer.

~~~
gcb
wow that was sure detailed.

but i'm still not convinced of the steps :)

($=[][(__=!$+$)[_=-~-~-~$]+({}+$)[_/_]+
($$=($_=!''+$)[_/_]+$_[+[]])])()[__[_/_]+__ [_+~$]+$_[_]+$$](_/_)

here i kept $, only step 11 required [] instead of $

i'm guessing step 14 is actually executed earlier... or that undefined has the
same effects as [] for most of those stringfying hacks. Update: no, undefined
trhows an error. so step 14 is earlier... let me replace all that with a eval
function that also stores the run order. then i will post the correct
ordering.

~~~
tlrobinson
No, step 14 is definitely executed after the rest of that expression. Steps 2,
3, 5, 8, and 10 assume that $ equals [].

If you still refuse to believe me, I give up.

------
Mc_Big_G
Perl puts that ugliness to shame.

