Всё больше набирают популярность вирусы, написанные для сайтов. Вы заходите на сайт, "Касперский" говорит, что сайт заражён вирусом. В действительности, сам вирус находится на одном из компьютеров, имеющих ftp доступ к сайту. Он незаметно для хозяина крадёт пароли от ftp, подключается и вставляет в скрипты сайта паразитный код. Чаще всего это скрытые ссылки на китайские сайты.
Вы обновляете свой антивирус, лечите заражённый компьютер, а сайт остаётся в нерабочем состоянии с большим количеством испорченных файлов. Искать код вручную задача не из приятных. Но можно упростить себе жизнь при помощи несложных скриптов.
[spoiler]
Полагаем, что информация, изложенная в
Простейший вариант
Для начала нужно найти все файлы, заражённые вирусом. Искать на дальнем хостинге не всегда возможно (нужен доступ ssh и специальные навыки или другие инструменты), скачать весь сайт на локальный компьютер тоже не лучший вариант (особенно если админка битрикса не работает вместе с системой резервного копирования). Но у нас всегда есть php! Поиск текста в файле по сути задача тривиальная, надо только прикрутить рекурсивное сканирование директорий и вот что получается:
<form method=post> <textarea name=code cols=80 rows=10><?=htmlspecialchars($_REQUEST['code'])?></textarea> <br><input type=submit name=go value="GO!"></form><? if ($_REQUEST['code']) { define('CODE', str_replace("\r\n","\n",$_REQUEST['code'])); define('START_PATH', dirname(__FILE__)); define('LOG',START_PATH.'/filelist.txt'); @unlink(LOG); Search(START_PATH); ?><iframe src=filelist.txt width=100% height=600></iframe><? } function Search($path) { if (is_dir($path)) // dir { $dir = opendir($path); while($item = readdir($dir)) { if ($item == '.' || $item == '..') continue; Search($path.'/'.$item); } closedir($dir); } else // file { if (substr($path,-4) == '.php') { $str = file_get_contents($path); $str = str_replace("\r\n","\n",$str); if (false !== strpos($str,CODE)) Mark($path); } } } function Mark($file) { static $res; if (!$res) $res = fopen(LOG,'wb'); if (!$res) die('no permissions'); fwrite($res,substr($file,strlen(START_PATH))."\n"); }?> |
Скрипт показывает форму для ввода кода вируса (или иного текста, который надо найти), затем начинает сканировать все файлы с расширением "php" в текущей папке и подпапках. Список найденных файлов сохраняется в filelist.txt, затем он выводится на экран.
Обратите внимание, скрипт написан для php5, на php4 потребуется заменять функцию file_get_contents
Вот как это выглядит у меня:
Но есть одна проблема: на хостинге не получится за один хит прочитать все php файлы сайта ввиду ограничения ресурсов. Чтобы решение было жизнеспособным надо выполнять его по шагам.
Пошаговый поиск
Потребуется следующее:
1. Уметь продолжать поиск из любого места, для этого нужно иметь точку входа и всякий раз "проматывать" на неё.
2. После выполнения ряда действий проверять лимит по времени, и если он исчерпан - прерывать выполнение, передав текущую точку себе же.
3. Проверить окончание и показать результат.
- Архитектурно скрипт немного изменится, теперь сверху будет собственно поиск, а форма ниже. До неё мы дойдём только по окончанию операции.
- В функцию поиска вставим проверку на истечение времени (10 секунд) и определение пути, на котором прервалась операция в константе BREAK_POINT.
- Если определена константа BREAK_POINT после вызова функции поиска - показываем форму, которая отправляет запрос со значением текущего пути.
- Для "прокрутки" к последней папке используем такой алгоритм: отбрасывается последний элемент текущего пути, если оставшаяся часть не является началом искомого пути - идём дальше. Проверка делается до тех пор, пока текущий путь не будет совпадать с искомым.
В итоге получился такой код:
<?if ($_REQUEST['code']){ define('START_TIME', time()); // засекаем время старта define('CODE', str_replace("\r\n","\n",$_REQUEST['code'])); // строка поиска define('START_PATH', dirname(__FILE__)); // стартовая папка для поиска define('LOG',START_PATH.'/filelist.txt'); // файл с результатами if ($_REQUEST['break_point']) define('SKIP_PATH',$_REQUEST['break_point']); // промежуточный путь else @unlink(LOG); // первый раз, удалим файл со старыми результатами Search(START_PATH); if (defined('BREAK_POINT')) { ?><form method=post id=postform> <input type=hidden name=go value=y> <input type=hidden name=code value="<?=htmlspecialchars(CODE)?>"> <input type=hidden name=break_point value="<?=htmlspecialchars(BREAK_POINT)?>"> </form> Идёт поиск...<br> Текущий файл: <i><?=htmlspecialchars(BREAK_POINT)?></i> <script>window.setTimeout("document.getElementById('postform').submit()",500);</script><? // таймаут чтобы браузер показал текст die(); } $iframe = "<iframe src=filelist.txt width=100% height=600></iframe>"; } else $iframe = ''; ?> <form method=post> <textarea name=code cols=80 rows=10><?=htmlspecialchars($_REQUEST['code'])?></textarea> <br><input type=submit name=go value="GO!"></form><? if (file_exists(LOG)) echo $iframe; function Search($path) { if (time() - START_TIME > 10) { if (!defined('BREAK_POINT')) define('BREAK_POINT', $path); return; } if (defined('SKIP_PATH') && !defined('FOUND')) // проверим, годится ли текущий путь { # /bitrix/components/bitrix/forum/message # /bitrix/components/alpha - годится # /bitrix/components/alpha/beta - не годится if (0!==strpos(SKIP_PATH, dirname($path))) // отбрасываем имя или идём ниже return; if (SKIP_PATH==$path) // путь найден, продолжаем искать текст define('FOUND',true); } if (is_dir($path)) // dir { $dir = opendir($path); while($item = readdir($dir)) { if ($item == '.' || $item == '..') continue; Search($path.'/'.$item); } closedir($dir); } else // file { if ((!defined('SKIP_PATH') || defined('FOUND')) && substr($path,-4) == '.php') { $str = file_get_contents($path); $str = str_replace("\r\n","\n",$str); if (false !== strpos($str,CODE)) Mark($path); } } } function Mark($file) { static $res; if (!$res) $res = fopen(LOG,'ab'); if (!$res) die('no permissions'); fwrite($res,substr($file,strlen(START_PATH))."\n"); }?> |
После запуска скрипт выглядит также, но добавился важный функционал пошаговой работы.
В результате получим filelist.txt, содержащий список заражённых файлов.
Резонный вопрос: а почему сразу не удалять вирус?
Потому что есть серьёзная опасность автозаменой потерять данные из своих скриптов.
Автоматическая замена
В чистом виде я умышленно не даю такое решение. Вы должны хорошо осознавать возможные последствия автоматического удаления кода. Изменения такие:
- В форму добавьте кнопку
<input type=submit name=cure value="CURE!">
- Определение функции Mark замените на
function Mark($file, $str) { static $res; if (!$res) $res = fopen(LOG,'ab'); if (!$res) die('no permissions: '.LOG); if ($_REQUEST['cure']) { copy($file,$file.'.orig'); $f = fopen($file,'wb'); if (!$f) die('no permissions: '.$file); fwrite($f, str_replace(CODE,'',$str)); fclose($f); } fwrite($res,substr($file,strlen(START_PATH))."\n"); }
- Добавьте соответственно второй аргумент в вызов этой функции
Теперь по нажатию кнопки "CURE!" введённый текст будет автоматически удаляться начиная с папки, где лежит сам скрипт, и ниже. Исходные файлы сохраняются с расширением "orig".
В текстовое поле надо будет ввести паразитный код целиком, иначе он удалится только частично и проблема только усугубится. Будьте предельно внимательны при выполнении такой операции, не забудьте сделать полную резервную копию!
Дополнено 25.06.2009г.
Немного изменённый скрипт из сообщения можно скачать по ссылке:
По умолчанию автозамена отключена. Чтобы включить - закомментируйте или удалите вторую строчку:
define('DisableReplace',true); |
Обновление от 04.09.2012
Нашел интересную утилиту для поиска вирусов на сайте:
допиливаем, для поиска обфусцированного кода и отправки мыла на имя админа, вешаем в крон, прёмся
Требуются специальные знания unix.
Но раньше вирусный код дописывался только в индексные файлы в папки на 2-3 уровня вложенности и только последней строкой.
И проще было вручную через фтп (не обязательно ssh) отсмотреть соответствующие файлы и вручную почистить, чем идти на такой риск, как автозамена через скрипт.
Скрипт полезный, комфортнее выходит, чем по ssh. Насчет ФАКа - поддерживаю, многим будет полезно!
P/s/ А пароли от ftp в тотал командоре хранить - себе дороже!
Очень кстати удобно удалять строчки через dreamweaver, он во всех файлах папки ищет и сам все удаляет, правда перед этим папки с сайтом скачать надо.
Только пароли уплыли не у меня и я не знал что с сайтом - просто ошибку стал выдавать по всем страницам. В т.ч. админку.
Доступа к ФТП не было (вот такие у меня отношения с заказчиком были, что у хакера доступ был, а у админа - нет)
Чтобы добраться до битрикс-админки пришлось использовать урлы страниц админки (тех, где вы общаетесь с какими-нибудь опциями конкретными, а не просто битрикс/админ/индекс.пхп). Те, что не содержат индекс.пхп. Ибо страдают обычно индекс (пхп, хтмл, схтмл и тд) файлы.
Самое неприятное, когда вредоносный код внедряют с разрывом пхп-тегов. И ифрейм не работает и файл умирает - так у меня было...
У меня был опыт со всеми вариантами вставки и в <iframe и в <?php и в <script, причем сложность вредоносных вставок росла и в последних "версиях" во вредоносный код вставлялись экранирующие символы, затруднявшие операции поиска и сравнения.
Иногда приходилось и такие конструкции писать: <?php if\(\!function_exists\(\'tmp_lko[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+><?
А если вы уверенно работаете с рег. выражениями - не должно быть проблем заменить одну функцию в скрипте
на
и будут лечиться js-скрипты.
А скрипт не может нормально искать, экранирует тэги. с заменой тоже самое.
Замените
В командной PHP-строке вставила предлагаемый вами итоговый текст кода, в котором в первой строке вместо код [code] вставила [HTML:IFrame[Trj] и запустила на выполнение. Но выдается ошибка Parse error: syntax error, unexpected '<' in /home/httpd/vhosts/lemurya.ru/httpdocs/bitrix/modules/main/admin/php_command_line.php(28) : eval()'d code on line 1
Скажите, как мне вылечить сайт
Очень прошу вас, напишите мне пошаговую инструкцию, что делать?
Если я удалю этот файл, я смогу удалить вирус на сайте или этого мало?
Жду с нетерпением ваш ответ. С уважением Светлана (lana88888@bk.ru)
Итоговый код надо сохранить в файл, его открыть, в окне выполнения php кода работать не будет.
Но на всех сайтах должен быть актуальный ключ чтобы мы могли залить последние версии модулей!
Подскажите, что можно сделать? Ручками править - повеситься, а в унихе я последний раз работал 15 лет назад....
Вирус перезаписывает файл htaccess который добавляет 150 строк кода, которые в итоге редиректят посетителей пришедших с поисковых систем на какойто сайт, где их просят ввести телефонный номер.
Благодаря выше описанному скрипту - нашел 2 файла на одном из сайтов:
Искал вхождение строки "se64_deco" было десяток битриксовских файлов и 2 подозрительных:
/bitrix/admin/template_import.php
/bitrix/admin/sale_stat_graph_user.php
Содержимое было одинаковое, с набором функций по созданию редактированию файлов, папок, уладения логов, бэкапов и т.д.
Хочу поинтересоваться было ли у когото что-то подобное? Боюсь что это не единственные файлы, и пока не особо радуюсь.
Последствия: всего за 2 дня Яндекс выкинул из выдачи все сайты, непонятно что теперь делать...
Вирус перезаписывает файл htaccess который добавляет 150 строк кода, которые в итоге редиректят посетителей пришедших с поисковых систем на какойто сайт, где их просят ввести телефонный номер.
У меня был файл /bitrix/admin/template_import.php
Откуда он взялся - я не знаю.
Как вы решили проблему?
(стандартный дешифрофщик PHP думаю использовался чтобы скрыть основную суть скрипта и усложнить его обнаружение)
А дальше уже дело техники - понять какие из найденных файлов битриксовские, а какие нет и удалить.
Либо можете попробовать обратиться к профессионалам (когда я искал - нашел нескольких людей они берут за очистку сайта в среднем 5000-7000 р.) но очень сомнительно, самому надежнее.
/bitrix/modules/altasib.comments/include.php
/bitrix/modules/altasib.comments/install/index.php
/bitrix/modules/iblock/admin/iblock_edit_property.php
/bitrix/modules/iblock/admin/iblock_edit.php
/bitrix/modules/security/classes/general/session.php
/bitrix/modules/security/classes/general/antivirus.php
/bitrix/modules/softeffect.awaygooff/include.php
/bitrix/modules/softeffect.awaygooff/install/index.php
/bitrix/modules/seo/admin/seo_tools.php
/bitrix/modules/main/tools.php
/bitrix/modules/main/spread.php
/bitrix/modules/main/admin/site_checker.php
/bitrix/modules/main/admin/event_log.php
/bitrix/modules/main/classes/general/captcha.php
/bitrix/modules/main/classes/general/controller_member.php
/bitrix/modules/main/classes/general/liveid.php/
bitrix/modules/blog/general/blog_metaweblog.php
Иван, удаление этих файлов помогло? Или как Вы решили эту проблему?
какой текст говорит о наличии вируса?
попали у касперского в стоп-лист. Как теперь оттуда выбраться?
Сменить пароли к хостингу, FTP, SSH, базе.
Сообщить хостеру о имевшием место заражении сайта. Возможно, заражение было через другой сайт на том же сервере, что и ваш. Пусть проверит.
Вычистить сайт. Проверьте все ява-скрипты, не только свои, но и ядра. Запустите тест проекта, проверьте, какие файлы ядра модифицировались, когда и кем. Внимательно просмотрите логи хоста - это, возможно, подскажет, как именно вредитель получил доступ к сайту. У меня гад старательно правил логи битрикса, но к логам хоста доступа не имел, что мне сильно помогло!
Внимательно проанализируйте политику прав доступа. Ограничьте, где возможно. Проведите среди персонала воспитательные мероприятия, опять же, если это возможно. К сожалению, мы, разработчики, вынуждены передавать админские логины/пароли заказчикам. Что нередко и приводит к подобным проблемам, потому что бардак!
Я еще отломал php-командную строку в админке. Просто сменил расширение файла. Если понадобится - подключить недолго. Хотя, я ей ни разу не пользовался
Когда сделаете все, напишите касперу, что исправились. Мы так в яндекс попали. Потом две недели оттуда вылезали, соответственно две недели мне заказчик мозг кушал.
На самом деле - очень удобный файловый менеджер, с кучей возможностей, с удобным доступом к SQL,командной строкой и прочими полезными фенечками! Компактный и быстрый. Битриксовские кодеры такого еще долго не сделают, так хоть содрали бы!!! Я бы с удовольствием сам им пользовался, взамен штатной оболочки, но касперский ругается
Еще вариант поиска "нехороших" файлов - запустить в админке в "настройках" тест проекта. Если вносились изменения в ядро - просмотреть какие файлы были изменены, анализировать код...
И еще, по поводу командной PHP-строки в админке - я у себя ее просто отключил сменой расширения у файла. Т.е. если она понадобится - легко включить, а так - не фиг
Я реализовал это пожелание в виде отдельного скрипта:
Все как-то очень подозрительно и одинаково, даже грешным делом на уязвимость подумываю, но вот с какого места она идет, пока не понятно.
Сайт заразился через веб-шелл WSO, я удалила сам скрипт шелла (в папке bitrix/admin/ под правами администратора был создан подозрительный файл 1.php), антивирус Битрикса постоянно удалял генерируемый на страницах код с ифреймом, а вот найти сам код вируса никак не удавалось. Пыталась выполнить поиск встроенными средствами битрикса, но код найти не удавалось, а с помощью скрипта сразу нашелся зараженный файлик. Огромный респект и спасибо:).
Кстати, может кому пригодится - заражен был файл prolog_after.php в папке /bitrix/modules/main/include
/bitrix/modules/main/include.php
Содержимое данного файла не имеет ничего общего с тем, что там должно быть на самом деле (судим по аналогам файла на других сайтах соответствующей редакции битрикс). Подскажите, пожалуйста, каким образом вернуть рабочий код данного файла? Без этого файла система не работает... код подобного файла с другого сайта не воспринимает... Очень ждем конструктивный ответ...