Разборы

Сайт на Битриксе взломали: как найти все закладки, а не только то, что нашел хостер

Хостер заблокировал аккаунт за вредоносную активность и прислал список зараженных файлов. Самое частое решение: удалить файлы из списка и попросить разблокировку. Через несколько дней все возвращается. В одной из моих чисток в списке хостера было 2 файла из примерно 25 работавших закладок, зато там же был помечен штатный файл Битрикса, без которого сайт падает целиком. Чтобы заражение не вернулось, чистить надо по-другому.

Как выглядит взломанный сайт

Чаще всего никак. Все разделы открываются, ошибок нет, владелец заходит на сайт и видит обычную страницу. При этом:

  • сайт падает в поиске Google или страницы выпадают из индекса;
  • в Search Console появляются чужие адреса или меры за спам;
  • хостер присылает уведомление о вредоносной активности или блокирует аккаунт.

Это клоакинг: подмена показывается только поисковому роботу. Посетителям из определенных стран дополнительно может включаться переадресация на чужой магазин. Обычная проверка в браузере заражение не покажет.

Проверка одной командой

Запросить главную страницу дважды: как Googlebot и как обычный браузер.

curl -s -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" https://example.ru/ -o gb.html -w "%{size_download}\n"
curl -s -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/131.0" https://example.ru/ -o br.html -w "%{size_download}\n"
grep -o -i "<title>[^<]*</title>" gb.html br.html

Если размер ответа и заголовок страницы различаются, клоакинг есть. В разобранном случае робот получал 183 КБ с японским заголовком про копии люксовых часов, браузер 54 КБ обычной главной.

Три уточнения:

  • проверяйте и Яндекс: подмена часто ловит только Google, YandexBot получает чистую страницу;
  • подмена бывает навешана только на главную, внутренние страницы чистые;
  • проверку лучше делать с самого сервера. Серия запросов с подделанным Googlebot снаружи может закончиться баном вашего IP фаерволом хостинга.

Где прячут закладку

Главная цель - файл, который выполняется на каждом запросе: bitrix/modules/main/include/prolog.php. Чужой код ставится в самое начало, до подключения движка. Оригинальный файл короткий, около 380 байт, и все, что стоит выше строки require_once, лишнее.

Самого спамного текста на сайте нет. Он подтягивается на лету с другого взломанного сайта, поэтому поиск по словам из подмены ничего не найдет.

Другие места, которые я находил:

  • языковые файлы в глубине bitrix/, которые никто не открывает;
  • редко используемые каталоги мастеров и публичных шаблонов;
  • PHP-файлы в каталогах картинок;
  • PHP внутри настоящей картинки: валидный PNG, после заголовка которого лежит код. Сам он не выполняется, его подключает однострочная закладка в безобидном файле страницы;
  • первая строка включаемой области: обычный текст страницы, а перед ним одна строка PHP;
  • вложенные каталоги-двойники вида kontakty/kontakty/;
  • .htaccess двух видов. Одни разрешают выполнять PHP в каталоге со шеллом. Другие запрещают весь PHP, кроме шеллов атакующего, и заодно ломают штатные скрипты Битрикса в этом каталоге.

Почему антивирус хостинга не помогает

Он ищет сигнатуры известных шеллов и пропускает:

  • короткие врезки в рабочие файлы: 900 байт внутри prolog.php ни под одну сигнатуру не подходят;
  • незнакомые ему обфускаторы;
  • честные файловые менеджеры, которые используются как шелл;
  • PHP в картинках и однострочные закладки;
  • .htaccess.

И при этом он может пометить штатный файл Битрикса bitrix/modules/main/lib/security/w/wwall.php. Это встроенный фаервол Битрикса, его код закрыт лицензионной обфускацией, и он скачивает правила с серверов Битрикса. Для эвристики антивируса это выглядит как троян. Удалять его нельзя: ядро вызывает его на каждом запросе, и без него падают все страницы. Правильно добавить файл в исключения сканера и объяснить хостеру.

Поэтому список хостера это отправная точка, а не задание на чистку.

Порядок работ

1. Ничего не удалять сразу

Сначала снять картину, потом менять. Все изменения вести скриптом с журналом действий и списком контрольных сумм. Если перезаписать зараженный файл до того, как сделана копия, образец потерян, а вместе с ним и понимание, как вас взломали.

2. Посмотреть весь аккаунт, а не один сайт

ls -la ~/domains/*/public_html/bitrix     # не общее ли ядро у нескольких сайтов
crontab -l                                # чужие задания по расписанию
cat ~/.ssh/authorized_keys                # чужие ключи
grep -rn "auto_prepend_file" ~/domains --include=.htaccess --include=.user.ini

Если bitrix на боевом сайте это ссылка на ядро тестового, то дыра на тесте автоматически работает на боевом.

3. Искать по дате изменения метаданных, а не по дате файла

Дату файла подделывают одной командой touch. В одном случае набор шеллов стоял с датой ровно на два года раньше реальной, секунда в секунду. Дату изменения метаданных (ctime) так не подделать, она меняется при любой записи.

find ~/domains -type f \( -iname "*.php*" -o -name ".htaccess" \) -newerct "2026-08-01" \
  ! -path "*/cache/*" ! -path "*/managed_cache/*" \
  -printf "%CY-%Cm-%Cd %CH:%CM | %TY-%Tm-%Td | %s | %p\n" | sort

Самый сильный признак - файлы, у которых дата файла старше даты метаданных больше чем на сутки. Значит, дату подделали:

find ~/domains -type f -newerct "2026-08-01" -printf "%C@ %T@ %p\n" | awk '($1-$2)>86400'

4. Сигнатуры и картинки

Шаблоны держать в файле, а не в командной строке: при запуске через ssh экранирование ломается, и grep молча ничего не находит. Проверьте шаблоны на заведомо зараженном файле.

grep -rlIE -f sig.txt --include="*.php" ~/domains
find ~/domains -type f -size -3M \( -iname "*.png" -o -iname "*.jpg" -o -iname "*.gif" -o -iname "*.ico" \) \
  ! -path "*/resize_cache/*" -exec grep -laE "<\?php|eval\(" {} +

В sig.txt строки вида eval\(base64_decode, eval\(gzinflate, eval\(\$_(POST|GET|REQUEST|COOKIE), Priv8, YAK Pro.

Найдя один файл, ищите его копии по всему аккаунту: по контрольной сумме, имени и уникальным строкам. Раскладка обычно веерная, одинаковые копии лежат на всех сайтах.

5. Карантин вместо удаления

Подозрительные файлы переносить в отдельный каталог с сохранением путей и списком контрольных сумм. Перед запуском антивируса хостера карантин зашифровать: антивирус проверяет весь домашний каталог и найдет шеллы в открытой папке.

Файлы ядра восстанавливать из оригинала. Эталоны для сверки: официальные пакеты обновлений в bitrix/updates/, чистая копия ядра на соседнем сайте, резервная копия.

После карантина прогнать все поиски заново.

6. Сменить доступы одновременно с чисткой

Не после, а вместе:

  • пароль панели хостинга и SSH, завершить все сеансы, включить двухфакторный вход;
  • пользователи FTP: лишних удалить, остальным новые пароли;
  • администраторы сайта: проверить список, лишних отключить;
  • пароль базы данных;
  • ключи платежных систем и API, которые лежат в файлах сайта. Шелл их читал.

7. Проверить результат и следить неделю

  • проверка подмены с сервера под Googlebot и браузером, все разделы, оплата;
  • неделю каждый день поиск новых файлов по ctime в ядре и корнях сайтов. Если закладки восстанавливаются, значит остался канал;
  • Search Console: чужие подтверждения домена, ручные меры, удаление мусорных адресов.

Грабли

Чистка не закончена, пока жив хоть один шелл на любом сайте аккаунта. Все сайты на одном аккаунте работают под одним пользователем, и шелл на заброшенном поддомене пишет в ядро боевого сайта. В одном случае каталог появился снова через 0,26 секунды после переноса, а врезка в ядро вернулась через три дня. Причиной были несколько шеллов на других доменах того же аккаунта.

Журналы хостер хранит недолго, иногда около 15 дней. Снимайте их в первые дни, иначе выяснить, как вас взломали, будет не по чему.

Отсутствие записей в журнале одного сайта ничего не доказывает, если у остальных сайтов журналов нет вообще.

Сколько это занимает

По моим двум последним чисткам: около 6 часов до письма хостеру (поиск и карантин, разбор находок и ложных срабатываний, шифрование и итоговая проверка, разбор блокировки) и еще 3-4 часа после разблокировки (пароли, проверка сайта и оплаты, контроль, поиск точки входа). На аккаунте с одним сайтом обычно быстрее.

Список для проверки

  1. Сравнили ответ сайта для Googlebot и для браузера?
  2. Посмотрели все сайты аккаунта, а не только тот, на который жаловались?
  3. Искали по ctime, а не по дате файла?
  4. Проверили картинки и .htaccess?
  5. Сменили все пароли вместе с чисткой?
  6. Не удалили штатные файлы Битрикса по списку антивируса?
  7. Следите за новыми файлами хотя бы неделю?

Если хостер уже заблокировал ваш сайт или вы видите подозрительные признаки, напишите мне. Начну с проверки подмены и списка того, что лежит на аккаунте, это занимает около часа.

Похожая проблема на вашем сайте? Напишите в Telegram или оставьте заявку.