Как вылечить php файлы
Никто не хочет, чтобы с его сайта пропали данные или ресурс стал источником заражения других устройств. Но такое случается, когда на сайт попадает вредоносный код, или, проще говоря, вирус.
Практика показывает, что в основном заражение сайта происходит через системы управления контентом (CMS) и плагины к ним. Вы либо скачиваете из неофициального источника уже зараженный файл. Либо скачиваете из официального, но продукт с ошибкой, о которой пока никто кроме хакеров не знает. Такие ошибки называют уязвимостями.
Хакеры постоянно сканируют интернет в поисках уязвимых сайтов. Когда находят — загружают в файлы сайта вредоносный код. Он-то и рассылает спам, перенаправляет пользователей на зараженные страницы или крадет данные.
Бывает и по-другому, но редко.
Как понять, что сайт заражен
Обычно о заражении сообщает браузер, настольный антивирус или панель веб-мастера. Чтобы удостовериться, проверьте с помощью бесплатных сервисов:
Что делать, если сайт заражен
Обновите программное обеспечение. Как только об уязвимостях становится известно, их исправляют и выпускают обновления. Устанавливайте обновления только с официальных сайтов: WordPress, Joomla!, Drupal.
Удалите пиратские плагины.Устанавливайте плагины только от официальных разработчиков. Если на каком-то сайте размещен бесплатный аналог платного плагина, то скорее всего он уже содержит вирус. Лучше заплатить за оригинальное ПО, чем лечить зараженный сайт.
Поменяйте пароли. Часто вирус попадает на сайт используя пароль от админских панелей FTP или CMS, которые крадет во взломанной почте или компьютере. Смените пароли доступа к панели управления сервером, FTP/SSH-аккаунтам, MySQL, CMS. Используйте сложные пароли: не менее 10 символов, заглавные и строчные буквы, цифры и специальные символы. Для быстрой генерации используйте бесплатные сервисы: 1, 2.
Настройте права доступа к файлам. Через FTP или ISPmanager установите права доступа к файлам сайта. Права определяют, кто может просматривать, записывать и исполнять код. Для файлов сайта подходит значение 644 (изменять содержимое может только администратор, читать и исполнять код — любой посетитель сайта), для директорий лучше установить 755 (администратор может читать и редактировать, все остальные — только читать содержимое).
Восстановите резервную копию. Если вы знаете, когда произошло заражение сайта, восстановите созданную до заражения резервную копию. Это избавит от необходимости «лечить» ресурс.
Заблокируйте неиспользуемые функции в файлах конфигурации PHP. В файле конфигурации PHP (php.ini) добавьте disable_functions к неиспользуемым функциям из вот этого списка: passthru, shell_exec, system, proc_open, popen, curl_exec, curl_multi_exec, parse_ini_file, show_source.
Лечим сайт вручную
Лечить сайт можно вручную и с помощью антивирусов.
Если вы умеете работать с консолью сервера, очистите код сайта вручную. Для начала найдите чужеродный код: проверьте зараженные файлы, сравните их с незараженными из резервной копии. После, используя тип файла и фрагмент кода, найдите все зараженные файлы и удалите вредоносный код.
Пример команды для поиска паттернов вирусов в файлах php* и htm* директории /var/www/*/data/www/.
grep -Rils —include=.{php,htm*} -e ‘b=4594’ -e ‘e2aa4e’ -e ‘v58f57b98 = 0’ -e ‘forexam@pandion.im’ -e ‘pathToDomains’ -e ‘if(navigator.userAgent.match(‘ -e ‘var vst = String.fromCharCode’ -e ‘Menufiles/jquery.js’ -e ‘i5463 == null’ -e ‘r57.gen.tr’ -e ‘/rsize.js’ -e ‘feelthesame.changeip.name’ -e ‘40,101,115,110,98,114,105,110’ -e ‘c99sh’ -e ‘Shell by’ -e ‘ sh_ver’ -e ‘.tcpflood’ -e ‘c999sh’ -e ‘Array(base64_decode’ -e ‘Attacker Perl File’ -e ‘bogel = ‘ -e ‘(!function_exists(«getmicrotime»))’ -e’$d=substr’ -e ‘WSO ‘ -e ‘r57shell’ -e ‘msg=@gzinflate(@base64_decode(@str_replace’ -e ‘6POkiojiO7iY3ns1rn8’ -e ‘ mysql_safe’ -e ‘sql2_safe’ -e ‘aHR0cDovLzE3OC4yMTEu’ -e ‘php function _’ -e ‘encodeURIComponent(document.URL)’ -e ‘; if(isset($_REQUEST’ -e ‘UdpFlood’ -e ‘udp://1.1.1.1’ -e ‘ (md5($_POST[‘ -e ‘header(«Location: http’ -e ‘fx29sh’ -e ‘c999sh_surl’ -e ‘c99sh’ -e ‘/request12.php’ -e ‘NlOThmMjgyODM0NjkyODdiYT’ -e ‘semi-priv8’ -e ‘JHNoX25hbWUgPSAiIj’ -e ‘$shell_name’ -e ‘UvUbjYH4eJNgF4E1fedl’ -e ‘killall -9’ -e ‘Angel Shell’ -e ‘c100.php’ -e ‘c2007.php’ -e ‘c99 mod Captain Crunch’ -e ‘$c99sh_updatefurl’ -e ‘C99 Modified By Psych0’ -e ‘php-backdoor’ -e ‘r577.php’ -e ‘wso shell’ -e ‘backdoor’ -e ‘eval(stripslashes(‘ -e ‘Backdoor’ -e ‘Set WSHshell’ -e ‘WSHshell.Run DropPath’ -e /var/www/*/data/www/
Лечим с помощью антивирусов
Если вы не умеете работать с консолью сервера, используйте готовые решения. Самые большие базы паттернов вирусов, распространенных в рунете, содержат два антивируса: Virusdie и AI-Bolit.
Virusdie
Платный инструмент. Автоматически находит вредоносный код и удаляет его. Помогает снять санкции браузера. С Virusdie работать просто, так как антивирус интегрирован с панелью управления веб-сервером ISPmanager.
ImunifyAV
Cканер вирусов. Проверяет сайт на взлом, вирусы и хакерские скрипты. ImunifyAV также интегрирован с ISPmanager: устанавливается по умолчанию и раз в месяц сканирует весь сайт. Чтобы лечить, нужно активировать платную версию.
Как предотвратить заражение
- Используйте программное обеспечение только из проверенных источников.
- Генерируйте сложные пароли и не храните их в браузере.
- Настройте создание резервных копий.
- Изолируете сайты друг от друга, для этого создавайте каждый сайт на отдельном пользователе.
- Используйте Virusdie постоянно.
- Используйте ISPmanager для единовременного обновления всех установленных скриптов, или модуль интеграции ISPmanager с Softaculous.
Источник
Добрый день, уважаемые Хабраюзеры!
Некоторое время назад, около месяца, на сервере нашей компании появился вирус. На одном из крупных проектов были поражены все *.js файлы. Ситуация обычная — в конец файлов был дописан вредоносный код. Яндекс выдавал предупреждение о заражении сайта и в техотдел пришло задание очистить его. Ситуация разрешилась достаточно быстро, проект был выгружен с чистого репозитория в продакшн, пароли сменили.
Однако вскоре со всех отделов компании в техотдел стали поступать жалобы о заражённых сайтах. Менеджерам жаловались клиенты, сеошники трубили что сайты теряют позиции. Началась настоящая эпидемия. Помимо *.js файлов, заражению подверглись так же *.php файлы, в конец которых был дописан код:
echo ‘https://somedomain.com/style.js’;
Такому масштабному заражению сервер был подвержен впервые. Мысли по этому поводу были разные, вплоть до бэкдора какого-нибудь недовольного уволенного сотрудника, решившего напакостить. Однако это не подтвердилось. Был написал shell скрипт очищающий *.php файлы, а с *.js файлами справлялись по-прежнему, выгрузкой из чистого репозитория. Пароли учётных записей доступов к сайтам, доступы к фтп — всё было изменено. Перевели всех кто работает с фтп на WinSCP и раздали файлы-ключи доступа.
Сервер потихоньку стал «выздоравливать» а сайты возвращаться в яндекс. Однако кроме более сотни сайтов клиентов на нашем сервере, есть клиенты использующие сторонние хостинги. Доступ по фтп, никакой командной строки и shell. Практически на всех сайтах используется самописная CMS (написанная N-ое количество лет назад) в связке с fckeditor’om или старыми версиями ckeditor’ов. В файл менеджере ckfinder’e проверка авторизованности реализована простым return true; Используй нехочу. Стоит также упомянуть что Множество заражённых *.js файлов выгрузкой чистого репозитория не излечить. Git на таких сайтах нами не используется, а большая часть бэкапов на хостингах хранится максимум 7 дней. А в виду того что сайты расположенные на сторонних хостингах, нами практически не мониторятся, все бэкапы так же были заражены.
В каждый файл вирус добавлял произвольное количество собственных копий, от одной до пяти (мне больше не встречалось) и все они имели различные имена переменных, имена функций и зацепиться за них было невозможно. Единственной неизменной частью кода каждого полиморфа являлся следующий участок кода:
=Array.prototype.slice.call(arguments).join(«»),
Он и был выбран для поиска вхождений по файлам. Были проверены Jquery библиотеки 1.6.3 и 1.7.2 и в исходном коде совпадений не было обнаружено. Значит последовательность можно было использовать.
Чтобы не возиться вручную с несколькими десятками *.js файлов на каждом сайте, было решено написать скрипт на php. Он должен сканировать все указанные ему файлы на предмет искомой строки. Для расширения кругозора, так сказать, было решено не использовать exec(), system() команды или, к примеру, библиотеку phpseclib. Алгоритм прост до безобразия: Скрипт сканирует все директории начиная от заданной, в поисках указанной строки в файлах поиска. Перед внесением изменений, скрипт бэкапит файл (ну всё же мало ли чего) и удаляет строку, в которой присутствует искомая подстрока. Построчная работа была выбрана в виду того, что вирус в файл записывался в одну строку.
Приведу пример кода вируса в *.js файле: pastebin.com/J0zRduQw
Разбирать его я не стал, кому интересно — в интернете много примеров разбора обфусцированного кода. Поэтому перейду сразу к коду сканера.
<?
/*
———————————————————————————-
dScaner Class — START
———————————————————————————-
*/
/*
*
* Класс — dScaner для сканирования директорий на наличие вредоносного кода в
* указанных типах файлов
*
* Разработчик: Денис Ушаков
* Дата разработки: 03-04-2012
* Версия разработки: 0.0.3
*
*/
Class dScaner {
// преобразуем входной параметр в массив
// $get_str — список параметров
// $separator — разделитель параметров в списке
function request($get_str, $separator)
{
if (isset($get_str) && !empty($get_str))
{
// эксплоадим строку в массив и возвращаем его
$obj = explode($separator, $get_str);
return $obj;
}
else
{
return false;
}
}
/*
*
* Функция поиска в файлах вхождения заданной строки:
*
* $this->find($path, $files_allowed, $requested_string);
*
* $path — путь до директории, от которой отталкиваться при сканировании
* $files_allowed — список файлов, которые подвергаются сканированию
* $requested_string — строка поиска
*
*/
function find($path = ‘./’, $files_allowed, $requested_string)
{
// исключаемые ссылки на директории и файлы, которые будут игнорироваться
$dir_disallow = array(‘.’, ‘..’, ‘.htaccess’, ‘.git’);
if(is_dir($path))
{
$temp = opendir($path);
while (false !== ($dir = readdir($temp)))
{
if ((is_dir($path . $dir)) &&
(!in_array($dir, $dir_disallow)) )
{
// если директория — сканируем её
$sub_dir = $path . $dir . ‘/’;
$this->find($sub_dir, $files_allowed, $requested_string);
}
elseif ((is_file($path . $dir)) &&
(!in_array($dir, $dir_disallow)) &&
(strpos($dir, $files_allowed) == true) &&
(strpos($dir, ‘_BACKUP’) == false) )
{
// Если файл
// получаем полный путь до него
$in_dir_file = $path . $dir;
// считываем файл в строку
$temporary_file = file_get_contents($in_dir_file);
// флаг найденного вхождения искомой строки
$file_founded = false;
// разбиваем файл на строки
$tf_strings = explode(«n», $temporary_file);
// обрабатываем каждую отдельно
foreach ($tf_strings AS $item)
{
$item = strval($item);
// если в строке есть вхождения искомого запроса
if (strpos($item, $requested_string) !== false)
{
$file_founded = true;
}
}
// если в файле найдена строка
if ($file_founded)
{
// выводим путь до файла в котором найдено вхождение
print «<span style=’display:block;
padding:5px;
border:1px solid #1f4f18;
background-color:#d5f5ce;
font-size:12px;
line-height:16px;
font-family:tahoma, sans-serif;
margin-bottom:-15px;’>» . $in_dir_file . » — в файле обнаружена искомая строка.<br>
</span><br>»;
}
}
}
closedir($temp);
}
}
/*
*
* Функция сканирования вредоносного кода:
*
* $this->scan($path, $files_allowed, $requested_string);
*
* $path — путь до директории, от которой отталкиваться при сканировании
* $files_allowed — список файлов, которые подвергаются сканированию
* $requested_string — строка, по которой определяется наличие вредоносного кода
*
*/
function scan($path = ‘./’, $files_allowed, $requested_string)
{
// исключаемые ссылки на директории и файлы
$dir_disallow = array(‘.’, ‘..’, ‘.htaccess’, ‘.git’);
if(is_dir($path))
{
$temp = opendir($path);
while (false !== ($dir = readdir($temp)))
{
if ((is_dir($path . $dir)) &&
(!in_array($dir, $dir_disallow)) )
{
// если директория — сканируем её
$sub_dir = $path . $dir . ‘/’;
$new_parent_dir = $path . $dir;
$this->scan($sub_dir, $files_allowed, $requested_string, $new_parent_dir);
}
elseif ((is_file($path . $dir)) &&
(!in_array($dir, $dir_disallow)) &&
(strpos($dir, $files_allowed) == true) &&
(strpos($dir, ‘_BACKUP’) == false) )
{
// Если файл
// получаем полный путь до него
$in_dir_file = $path . $dir;
// считываем файл в строку
$temporary_file = file_get_contents($in_dir_file);
// флаг бекапа файла
$create_backup = false;
// разбиваем файл на строки и считываем каждую отдельно
$tf_strings = explode(«n», $temporary_file);
// индекс строки файла
$str_index = 0;
// каждую строку обрабатываем отдельно
foreach ($tf_strings AS $item)
{
$item = strval($item);
if (strpos($item, $requested_string) !== false)
{
// если в строке есть вхождения искомого запроса
// флаг бекапа файла, в котором найден вредоносный код
$create_backup = true;
// удаляем всю строку с вредоносным кодом
unset($tf_strings[$str_index]);
}
$str_index++;
}
// создаём бэкап
if ($create_backup)
{
// меняем права в папке в которой находимся чтобы иметь возможность писать в неё
chmod($path, 0777);
// формируем имя БЭКАПа файла
$temp_file_backup = $in_dir_file.’_BACKUP’;
// сохраняем БЭКАП файла рядом с исходным
file_put_contents($temp_file_backup, $temporary_file);
// собираем очищенный файл в строку
$scanned_file = implode(«n», $tf_strings);
// сохраняем очищенный файл
if (file_put_contents($in_dir_file, $scanned_file))
{
// перезаписали удачно
print «<span style=’display:block;
padding:5px;
border:1px solid #1f4f18;
background-color:#d5f5ce;
font-size:12px;
line-height:16px;
font-family:tahoma, sans-serif;
margin-bottom:-15px;’>» . $in_dir_file . » — Файл очищен. (+ BACKUP) <br>
</span><br>»;
}
else
{
// перезапись не удалась
print «<span style=’display:block;
padding:5px;
border:1px solid #822121;
background-color:#ea7575;
font-size:12px;
line-height:16px;
font-family:tahoma, sans-serif;
margin-bottom:-15px;’>».$in_dir_file .» — Файл НЕ очищен.
</span><br>»;
}
// меняем права в папке в которой находимся обратно на 755
chmod($path, 0755);
}
}
}
closedir($temp);
}
}
/*
*
* Функция восстановления БЭКАПОВ файлов
*
* $this->restore_backups($path, $files_allowed);
*
* $path — путь до директории, от которой отталкиваться при восстановлении
* $files_allowed — список файлов, которые подвергаются восстановлению
*
*/
function restore_backups($path = ‘./’, $files_allowed)
{
// исключаемые ссылки на директории и файлы
$dir_disallow = array(‘.’, ‘..’, ‘.htaccess’, ‘.git’);
if(is_dir($path))
{
$temp = opendir($path);
while (false !== ($dir = readdir($temp)))
{
if ((is_dir($path . $dir)) &&
(!in_array($dir, $dir_disallow)) )
{
// если директория — сканируем её
$sub_dir = $path . $dir . ‘/’;
$this->restore_backups($sub_dir, $files_allowed);
}
elseif ((is_file($path . $dir)) &&
(!in_array($dir, $dir_disallow)) &&
(strpos($dir, $files_allowed) == true) )
{
// Если файл
// получаем полный путь до него
$in_dir_file = $path . $dir;
if (is_file($in_dir_file.’_BACKUP’))
{
// БЭКАП существует, получаем его содержимое
$temporary_file_from_backup = file_get_contents($in_dir_file.’_BACKUP’);
// восстанавливаем бэкап файла
if (file_put_contents($in_dir_file, $temporary_file_from_backup))
{
// удаляем бэкап
unlink($_SERVER[‘DOCUMENT_ROOT’].’/’.$in_dir_file.’_BACKUP’);
// бэкап восстановили
print «<span style=’display:block;
padding:5px;
border:1px solid #1f4f18;
background-color:#d5f5ce;
font-size:12px;
line-height:16px;
font-family:tahoma, sans-serif;
margin-bottom:-15px;’>».$in_dir_file .» — восстановлен.
</span><br>»;
}
else
{
// бэкап НЕ восстановили
print «<span style=’display:block;
padding:5px;
border:1px solid #822121;
background-color:#ea7575;
font-size:12px;
line-height:16px;
font-family:tahoma, sans-serif;
margin-bottom:-15px;’>».$in_dir_file .» — НЕ восстановлен.
</span><br>»;
}
}
}
}
closedir($temp);
}
}
}
/*
———————————————————————————-
dScaner Class — END
———————————————————————————-
*/
?>
Код класса довольно подробно закоментирован, вопросов возникнуть не должно.
Пример использования (первый параметр — стартовая директория поиска, второй — тип файлов, учавствующих в поиске, третий — строка поиска):
Создаём экземпляр сканера.
$dron = new dScaner;
Прежде чем что-то перезаписывать, стоит посмотреть, есть ли файлы удовлетворяющие условиям поиска.
$dron->find(‘./’, ‘.js’, ‘=Array.prototype.slice.call(arguments).join(«»),’);
Запускаем зачистку.
$dron->scan(‘./’, ‘.js’, ‘=Array.prototype.slice.call(arguments).join(«»),’);
В случае чего, всегда можно восстановить созданные бэкапы.
$dron->restore_backups(‘./’, ‘.js’);
Сканер был протестирован на многих сайтах и отрабатывает как нужно, единственная проблема которая возникла у нас на сервере — права владельца файла. Нужно чтобы owner’om файла был www:www. В среднем, на один сайт с нескольким десятком *.js файлов уходило от 5-10 до 20 секунд. И привожу список хостингов, на которых скрипт был успешно протестирован: infobox, agava, jino, mchost, hc. Из всех, самым замедленным был mchost, на остальных всё работало достаточно шустро.
P.S. Скрипт не претендует на панацею от вирусов, разработан под конкретный случай заражения и под каждый последующий требует доработки. Однако с поставленной задачей отлично справляется. Надеюсь, кому-то будет полезен.
Бест регардс!
Источник
Проанализируйте способы заражения:
Злоумышленник может получить пароли к администраторским панелям CMS, FTP или SSH аккаунтам. Обычно пароли подбирают или крадут с помощью троянских программ, заразивших компьютер вебмастера.
Уязвимости веб-приложения могут позволять посторонним размещать на сайте произвольный код.
Из-за заражения внешнего ресурса (партнерской программы, баннерной системы, счётчика) предоставленный вам код может стать опасным для пользователей.
Проанализируйте информацию о заражении в Яндекс.Вебмастере, в разделе Безопасность и нарушения. Раздел содержит перечень зараженных страниц, даты проверок и вынесенные антивирусом вердикты. Перейдя по ссылке в названии вердикта, вы увидите его описание и примерный вид кода, соответствующего вердикту (кода, который непосредственно появляется на страницах сайта).
Вы также можете самостоятельно воспроизвести проблему с помощью виртуальной машины.
Остановите веб-сервер, чтобы оградить посетителей сайта от потенциальной опасности. Затем проверьте антивирусом файлы веб-сервера и все рабочие станции, с которых администрируют сервер (можно использовать бесплатные антивирусные утилиты) и смените все пароли: root, FTP, SSH, от административных панелей хостинга и CMS.
Если до заражения была сделана резервная копия сайта, восстановите ее.
Обновите до последних версий все используемые сайтом программы и поищите описания исправленных уязвимостей. Возможно, это поможет понять, каким образом сайт был заражен.
Удалите лишних пользователей с расширенными правами и тщательно проверьте сервер на наличие веб-шелла, с помощью которого злоумышленник может изменять код сайта в обход авторизации.
Проверьте наличие вредоносного кода:
во всех серверных скриптах, шаблонах CMS, базах данных;
в конфигурационных файлах веб-сервера или интерпретатора серверных скриптов;
если вы используете shared-хостинг, проверьте другие сайты, расположенные на том же сервере — может быть заражен весь сервер.
Признаки вредоносного кода:
Код посторонний или незнакомый, не соответствует резервной копии или системе контроля версий.
Обфусцированный (нечитаемый, неструктурированный) код.
Дата модификации файлов совпадает с временем заражения или более поздняя. Этот параметр ненадежен, так как дата модификации файлов может быть изменена вирусом.
Использование характерных для вредоносного кода функций. Примеры таких функций для языка PHP:
динамическое исполнение кода (eval, assert, create_function);
обфускация (base64_decode, gzuncompress, gzinflate, str_rot13, preg_replace);
загрузка удаленных ресурсов (file_get_contents, curl_exec).
Пометка об опасности сайта в результатах поиска будет снята, если при очередной проверке робот Яндекса не обнаружит заражения. Чтобы ускорить перепроверку, в интерфейсе Яндекс.Вебмастера, в разделе Безопасность и нарушения, нажмите кнопку Я все исправил.
Рекомендуем в течение нескольких недель после заражения регулярно перепроверять файлы и код сайта на тот случай, если использованная уязвимость не была устранена или злоумышленники по прежнему имеют доступ к сайту.
Яндекс постоянно ищет и исследует новые виды заражений и публикует результаты исследований в блоге Безопасного поиска Яндекса.
Если вы обнаружили на своем сайте вредоносный или подозрительный код, отправьте его на анализ специалистам.
Чтобы ваш вопрос быстрее попал к нужному специалисту, уточните тему:
Источник