Бесплатный экспресс-аудит сайта Безопасность, SEO, AI-поиск и 152-ФЗ — отчёт с баллами за минуту Проверить сайт
Обсудить проект

Взломанный сайт на 1С-Битрикс: чистка, защита от возврата и переход на PHP 8.2 без обновления ядра

Оценить кейс

«Нас взломали, помогите» — с этого начался проект. Сайт на 1С-Битрикс, несколько лет без обновлений, подрядчик, который его делал, давно не отвечает, лицензия на обновления истекла. Связка распространённая, и работа по ней выстраивается в понятный порядок с понятным объёмом. Рассказываем его, чтобы владелец похожего сайта мог проверить у себя то же самое и представлял, чего ждать.

Имя клиента и домен не называем, остальное — как было.

Коротко о проекте

КлиентПоставщик металлопроката, название не раскрывается
СитуацияСайт взломан, обновлять ядро нельзя: лицензия истекла, прежний подрядчик недоступен
Что нашлиПоисковый клоакинг под азиатские казино, шесть веб-шеллов, две волны заражения
Что сделалиРазбор и чистка через карантин, запрет исполнения PHP в папках записи, смена всех паролей, переход с PHP 7.3 на 8.2 без обновления ядра
МасштабОколо 700 адресов, 1С-Битрикс 21.850, тема Aspro, общий хостинг
СрокиДва вечера: разбор с чисткой, затем закрытие путей возврата и перевод на PHP 8.2
ПростойНет: сайт работал всё время

Взлом, которого владелец не видел

Первые пятнадцать минут в консоли дали четыре находки подряд. Папка /bitrix/ стояла с правами 777 — писать в неё мог любой скрипт на том же хостинге, в том числе чужой. В корне лежали файлы, которых в стандартной сборке Битрикса нет: один на 200 КБ, другой со случайным набором букв перед index.php. Корневой .htaccess был переписан, а рядом аккуратно лежал .htaccess_back — атакующий сохранил оригинал, чтобы при случае вернуть всё как было. И в самом начале главного index.php стояла длинная строка запутанного кода.

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

  • пришёл робот Google или Bing — скрипт ходил на чужой сервер и отдавал роботу страницу с рекламой букмекеров;
  • пришёл человек, у которого в браузере стоит тайский язык, — его перебрасывало в онлайн-казино;
  • пришёл владелец сайта из России — он не видел ничего.

Зарабатывают на этом так. Взломанный сайт — чужой, с живой историей и доверием поисковика, и его бесплатно используют как донора: робот видит на нём страницы про ставки и начинает показывать сайт в тайской выдаче по игорным запросам. Человек, кликнувший по такой строчке, попадает на сайт поставщика металлопроката, но видит не его, а редирект в казино. Казино платит за приведённых игроков, то есть владелец сайта своим хостингом и своей репутацией оплачивает чужой поток клиентов.

Поэтому такие схемы живут месяцами. Владелец замечает не подмену страниц, а падение трафика: поисковики рано или поздно понижают сайт, через который раздают чужую рекламу. К этому моменту позиции уже потеряны, и возвращать их дольше, чем чистить файлы.

Что было внутри

Поиск по сигнатурам показал, что главной страницей дело не ограничилось:

  • Шесть веб-шеллов двух типов. Три тяжёлых — запутанные загрузчики, разложенные по корню, служебной папке админки и временному каталогу. Три лёгких — одинаковые файловые менеджеры с паролем 123456, спрятанные в папках с картинками и в разделе кабинета.
  • Два подменённых .htaccess с белым списком имён файлов: вызывать разрешено только то, что нужно атакующему, остальной PHP закрыт — чтобы сканеры безопасности ничего не нашли.
  • Две точки внедрения кода: главная страница и поддельная HTML-заглушка в корне.
  • Две волны по датам файлов. Первая — за три месяца до обращения, вместе с ней в /bitrix/ появились архивы сайта почти на гигабайт. Вторая — через десять дней после того, как владелец заметил неладное и сам закрыл несколько папок: атакующий просто переустановил шелл во временный каталог.

Вторая волна объясняет, почему чистка файлов сама по себе не помогает: пока в папку можно положить скрипт и выполнить его, всё вернётся за неделю.

Чистка: карантин вместо удаления

Ничего удалять сразу не стоит. Подозрительные файлы уезжают в карантинную папку с правами 700 за пределами сайта, недоступную по HTTP. Если вместе с заразой уехало что-то нужное, это возвращается одним движением, а не восстанавливается из резервной копии недельной давности вместе с потерянными заказами. Заодно остаются образцы: по ним видно, что искать в остальных местах.

Порядок был такой:

  1. Все найденные шеллы, подменённые .htaccess и поддельная заглушка — в карантин. Заражённая копия главной страницы сохранена отдельно, до чистки.
  2. Чистый index.php собрали заново: в заражённой версии законный код было видно сразу после вставки.
  3. Исходный .htaccess восстановили из .htaccess_back — того самого, который сохранил атакующий.
  4. Сняли права 777 там, где их быть не должно.
  5. Сменили все пароли: доступ к серверу, администратор сайта, база данных.
  6. Повторный поиск по сигнатурам — ни одного совпадения, главная отдаёт нормальную страницу.

На смене пароля администратора всплыла отдельная сложность: сайт работал на старом ядре, а консольный PHP на хостинге уже был восьмой версии, и штатный способ сменить пароль из консоли падал с ошибкой. Пароль пришлось пересобрать вручную и записать в базу — способ рабочий, и он же показывает, в какой вилке живёт сайт со старым ядром и новым окружением.

Чтобы не вернулось

Опасна здесь сама возможность выполнить PHP из папок, куда сайт пишет файлы. Попал скрипт в /upload/, кеш или временный каталог — и у атакующего снова есть шелл. Поэтому исполнение PHP в таких папках закрывается полностью:

<FilesMatch "\.(php|phtml|pl|cgi|py)$">
  Require all denied
</FilesMatch>
<IfModule mod_php.c>
  php_flag engine off
</IfModule>

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

Заодно по корневому .htaccess: закрыли скачивание архивов и дампов, служебных файлов вроде .env, заблокировали типовые пути сканеров и их узнаваемые подписи, добавили заголовки безопасности. И включили проактивную защиту Битрикса — она была выключена.

Нюанс общего хостинга. Запрет на скачивание архивов сначала не сработал: тестовый запрос к файлу на полгигабайта в /bitrix/ вернул 200. Причина в устройстве площадки — перед Apache стоит nginx и отдаёт статику сам, не заглядывая в .htaccess. Это не ошибка настройки, так устроено на большинстве общих хостингов. Значит, резервные копии и дампы нельзя держать внутри сайта — их место за пределами публичной папки. Архивы мы убрали.

Отдельная бомба — старый PHP

Сайт работал на PHP 7.3, поддержка которой закончилась в декабре 2021 года. Несколько лет без исправлений безопасности — и это не абстрактный риск: критические уязвимости в PHP выходят регулярно, а на неподдерживаемой версии каждая остаётся открытой навсегда. Свежий пример мы разбирали отдельно — две уязвимости с оценкой 9,2 из 10, обе позволяют выполнить чужой код на сервере. К этому проекту они отношения не имеют, он закончился раньше. Но именно так старый PHP и становится входной дверью.

Обновить ядро Битрикса было нельзя — лицензия на обновления истекла. Оставался второй путь: перевести сайт на PHP 8.2, не трогая ядро. Старое ядро с темой Aspro современный PHP не любит, но сломалось около десяти файлов. Все правки минимальные: проверки is_array() и is_string() там, где код полагался на мягкое поведение старого PHP, замена конструкций, запрещённых в восьмой версии, и несколько методов, которые пришлось объявить статическими. Поведение кода при этом не менялось, рядом с каждым правленым файлом осталась копия до правки.

Сначала подробный журнал ошибок, потом смена версии PHP — этот порядок экономит часы. Иначе Битрикс на каждую ошибку покажет свою заглушку «Произошла ошибка», и придётся гадать, что именно упало. С журналом работа идёт по кругу: переключили версию, прошли по страницам, увидели в журнале, что упало, поправили, повторили.

Одна ошибка после этого всё равно «залипла»: страница продолжала показывать сообщение об исключении, хотя причина была устранена, а журнал оставался пустым. Дело было в композитном кеше — Битрикс держит готовый HTML отдельными файлами, и сервер отдаёт их напрямую, не запуская PHP. После очистки этого кеша страница стала чистой. К концу вечера все страницы отвечали кодом 200. Проект с таким ядром и этой темой мы видели впервые.

Что проверить у себя

Короткий список для тех, у кого похожая связка: старый Битрикс, давно без обновлений, подрядчик недоступен.

  1. Есть ли в корне и в папках /upload/, /bitrix/tmp/, /bitrix/cache/ файлы, изменённые за последний месяц, которых вы не ждёте?
  2. Нет ли в .htaccess длинного белого списка имён файлов вроде back.php или reback.php? Это характерный признак набора для взлома.
  3. Что сайт отвечает поисковому роботу? Запросите главную с подписью робота Google — не отдаётся ли чужая страница: curl -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" https://вашсайт.ру/
  4. В списке администраторов сайта — только знакомые люди?
  5. Какая версия PHP работает сейчас? Ветка 7.x не получает исправлений безопасности с 2021–2022 годов.
  6. Включена ли проактивная защита Битрикса и когда последний раз запускалась проверка системы?
  7. Где лежат резервные копии? Если внутри сайта — их может скачать кто угодно.

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

Как мы беремся за такие проекты

Работаем в одном и том же порядке. Сначала разбор: что именно происходит, какие файлы заражены, когда и через что вошли. Потом чистка с карантином и проверкой, что вычищено всё. Потом закрытие путей возврата и смена паролей. И только после этого разговор о развитии — обновлении ядра, переходе на поддерживаемую версию PHP, нормальном резервном копировании за пределами хостинга.

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

Кейс был полезен?

Оцените первым — так другие поймут, стоит ли читать

Частые вопросы

Как понять, что сайт заражён, если внешне всё в порядке?

Поисковый клоакинг прячется от владельца: чужая страница отдаётся только роботам поисковиков или посетителям из нужной атакующему страны. Проверяют это запросом с подписью поискового робота и просмотром файлов: лишние PHP в корне и папках загрузки, подменённый .htaccess с белым списком имён, свежие даты изменения у файлов, которые никто не трогал. Косвенный признак — падение показов в Вебмастере без видимых причин.

Можно ли просто удалить заражённые файлы?

Можно, но рискованно: вместе с закладками легко удалить нужный код, а образцы понадобятся, чтобы понять, через что вошли, и найти остальные закладки. Мы переносим подозрительные файлы в карантинную папку за пределами сайта с правами 700 — оттуда их можно вернуть одним движением, и по HTTP они недоступны.

Почему после чистки заражение возвращается?

Потому что вычистить файлы мало. Пока в папки, куда сайт пишет, можно положить скрипт и выполнить его, любая следующая дыра в стороннем модуле снова даст доступ. В этом проекте вторая волна пришла через временный каталог Битрикса. Исполнение PHP в таких папках нужно закрывать и проверять тестовым файлом, что запрет работает.

Что делать, если лицензия на обновления Битрикса истекла, а сайт нужно защитить?

Обновление ядра — не единственный путь. Закрывается исполнение PHP в папках записи, резервные копии и дампы выносятся за пределы публичной директории, обновляется версия PHP до поддерживаемой. В этом проекте сайт перешёл с PHP 7.3 на 8.2 без обновления ядра: правок потребовалось около десяти файлов, и каждая из них минимальная.