Вирус на сайте: как найти, удалить и не допустить повторения
Взлом сайта малого бизнеса почти никогда не бывает «точечным». Никто не охотится конкретно за вашим сайтом: боты массово сканируют интернет в поисках известных уязвимостей в старых плагинах и CMS, слабых паролей и забытых файлов. Найдя дыру, они встраивают код, который зарабатывает на ваших посетителях — редиректами, спамом, майнингом. Разберу, как понять, что сайт заражён, и что с этим делать.
Признаки заражения
- Редиректы. Посетители с мобильных или из поиска попадают на чужие сайты. Часто вы сами этого не видите: вредоносный код показывает редирект только тем, кто пришёл из Яндекса, или только один раз на IP.
- Чужие страницы в поиске. Введите в Яндексе site:ваш-домен.by и пролистайте выдачу. Страницы на японском, про лекарства или казино — явный признак.
- Предупреждения. Яндекс помечает сайт «Сайт может угрожать безопасности вашего компьютера», браузер показывает красный экран.
- Письма от хостинга о рассылке спама или превышении нагрузки.
- Новые администраторы в админке, которых вы не создавали.
- Странные файлы в корне сайта и в папке загрузок: случайные имена, .php в /uploads/, файлы с датой изменения сегодня.
- Сайт стал медленным без видимой причины — возможен майнер или рассылка.
Первые действия
- Не паникуйте и ничего не удаляйте сразу. Удаление файлов наугад стирает следы, по которым ищется точка входа.
- Сделайте полную копию текущего, заражённого состояния: файлы, база, логи доступа.
- Смените пароль хостинга и почты, на которую зарегистрирован хостинг.
- Проверьте Яндекс Вебмастер — раздел «Безопасность и нарушения». Там бывает указан пример заражённой страницы и тип угрозы.
Где прячется вредоносный код
Файлы
- index.php, wp-config.php, config.php в начале или в конце файла;
- .htaccess — правила перенаправления по User-Agent или Referer;
- папки загрузок (/wp-content/uploads/, /image/, /upload/) — PHP-файлы там быть не должно;
- темы и плагины, особенно неиспользуемые;
- файлы с именами, похожими на системные: wp-tmp.php, class-wp-cache.php в неожиданном месте.
Поиск типичных конструкций по SSH:
grep -rlE "eval\s*\(\s*(base64_decode|gzinflate|str_rot13)" --include=*.php .
find . -name "*.php" -path "*uploads*"
find . -name "*.php" -mtime -7
Первая команда находит файлы с типичной обфускацией, вторая — PHP в папке загрузок, третья — PHP-файлы, изменённые за последнюю неделю.
База данных
- в WordPress: таблица wp_options (siteurl, home, виджеты), wp_posts (внедрённые скрипты в тексте записей), wp_users (лишние администраторы);
- в OpenCart: настройки в oc_setting, тексты категорий и товаров;
- в Битриксе: настройки модулей, содержимое инфоблоков.
Поиск в базе по характерным строкам:
SELECT ID, post_title FROM wp_posts WHERE post_content LIKE '%<script%' AND post_content LIKE '%eval%';
SELECT user_login, user_email, user_registered FROM wp_users ORDER BY user_registered DESC LIMIT 10;
Cron и задания
Злоумышленник может добавить задание в cron хостинга, которое заново загружает вредоносный файл. Проверьте планировщик в панели хостинга и crontab -l.
Как чистить
1. Сравните ядро с оригиналом. Скачайте ту же версию CMS и сравните файлы. Для WordPress есть команда:
wp core verify-checksums
wp plugin verify-checksums --all
Изменённые файлы ядра проще заменить оригинальными целиком.
2. Переустановите плагины и темы из официальных источников, вместо того чтобы чистить каждый файл. Неиспользуемые — удалите.
3. Проверьте вручную всё, что нельзя переустановить: дочернюю тему, свои модули, конфигурацию, .htaccess.
4. Очистите базу от внедрённых скриптов и лишних пользователей.
5. Удалите PHP-файлы из папок загрузок и запретите там выполнение PHP. Для nginx:
location ~* /(?:uploads|files|image)/.*\.php$ { deny all; }
Для Apache — файл .htaccess в папке загрузок:
<FilesMatch "\.php$">
Require all denied
</FilesMatch>
6. Смените все пароли и ключи: администраторы, FTP, SSH, база данных, ключи и соли в wp-config.php (новые можно сгенерировать на api.wordpress.org/secret-key/1.1/salt/).
Найдите точку входа
Без этого заражение вернётся через несколько дней. Смотрите логи доступа за период до появления первых вредоносных файлов:
grep "POST" access.log | grep -v "wp-cron\|admin-ajax" | awk '{print $7}' | sort | uniq -c | sort -rn | head
Типичные точки входа:
- уязвимый плагин или модуль старой версии;
- украденный пароль FTP — часто с компьютера, где он был сохранён в FTP-клиенте;
- слабый пароль администратора и отсутствие защиты от перебора;
- забытые файлы: установщики, adminer.php, старые копии сайта в подпапке.
Снятие пометки в Яндексе и Google
После очистки:
- Яндекс Вебмастер — «Безопасность и нарушения» — кнопка «Я всё исправил». Перепроверка занимает от нескольких дней.
- Google Search Console — «Проблемы безопасности» — «Запросить проверку» с описанием, что сделано.
Если после перепроверки пометка осталась — значит, на сайте ещё есть заражение. Чаще всего это код, который показывается только поисковым роботам.
Профилактика
- Обновляйте CMS, темы и модули — большинство взломов идут через известные уязвимости, для которых давно есть исправления.
- Удаляйте всё, что не используется.
- Сложные пароли, двухфакторная аутентификация для администраторов.
- Ограничьте вход в админку: защита от перебора, по возможности — доступ только с ваших IP.
- Запретите выполнение PHP в папках загрузок.
- Отключите редактирование файлов из админки (в WordPress — DISALLOW_FILE_EDIT).
- Регулярные резервные копии вне хостинга.
Если сайт заражён и хочется, чтобы им занялся человек, который делает это регулярно, — это услуга «Лечение сайта от вирусов». А чтобы не возвращаться к этой проблеме — техподдержка с обновлениями и контролем изменений файлов.
Как выглядит вредоносный код
Чтобы не удалить лишнее и не пропустить нужное, полезно знать типичные приёмы:
- Обфускация. Код упакован в base64, gzip и rot13 и распаковывается при выполнении: eval(gzinflate(base64_decode(‘…’))). Сами по себе эти функции бывают и в нормальных плагинах, но длинная нечитаемая строка, передаваемая в eval, — почти всегда вредонос.
- Маскировка под системные файлы. Файлы с именами wp-load-cache.php, class-plugin-update.php в неожиданных папках, иногда с датой изменения, подделанной под дату соседних файлов.
- Внедрение в начало легитимного файла. Первая строка index.php или wp-config.php очень длинная, а остальной файл выглядит нормально.
- Условное поведение. Код показывает редирект только мобильным посетителям, только пришедшим из поиска или только один раз с одного IP, поэтому владелец сайта его не замечает.
- Скрипт в базе. В тексте записей, виджетах или настройках темы вставлен тег script с внешним адресом.
Пример поиска в базе WordPress
Внешние скрипты, вставленные в записи и опции:
SELECT ID, post_title FROM wp_posts WHERE post_content REGEXP '<script[^>]+src=' ;
SELECT option_name FROM wp_options WHERE option_value LIKE '%<script%' OR option_value LIKE '%eval(%';
Найденное проверяйте вручную: счётчики Метрики и виджеты чатов тоже содержат script.
Контроль изменений файлов
Лучшая ранняя диагностика — знать, какие файлы изменились. На своём сервере простой вариант:
find /var/www/site -type f -name "*.php" -newermt "2026-10-01" ! -path "*/cache/*"
Команда выводит PHP-файлы, изменённые после указанной даты. Если вы не обновляли сайт, а файлы изменились — повод разбираться. На поддержке я делаю такие проверки регулярно и сравниваю с эталонной копией.
Чем опасен взлом помимо редиректов
- Рассылка спама с вашего сервера и попадание домена в чёрные списки — потом перестают доходить письма с сайта и обычная почта.
- Утечка данных клиентов, если злоумышленник получил доступ к базе.
- Потеря позиций: поисковики понижают и помечают заражённые сайты.
- Блокировка хостингом.
Как снизить риск повторного взлома
- Оставьте на сайте только нужные плагины и модули, удалите отключённые — их файлы тоже уязвимы.
- Включите двухфакторную авторизацию для администраторов, если CMS это поддерживает.
- Ограничьте доступ к админке по IP или поставьте дополнительную авторизацию на уровне сервера.
- Запретите редактирование файлов из админки: в WordPress это константа DISALLOW_FILE_EDIT.
- Проверьте права на файлы: 644 для файлов, 755 для папок, конфигурация — только для владельца.
- Настройте ежедневные резервные копии с хранением минимум две недели — иногда заражение замечают не сразу.
Чек-лист после взлома
- Копия заражённого сайта и логов.
- Смена паролей хостинга и почты.
- Сверка ядра CMS с оригиналом, переустановка плагинов и тем.
- Ручная проверка своих файлов, .htaccess, cron и базы.
- Удаление PHP из папок загрузок и запрет на выполнение.
- Поиск точки входа по логам и её закрытие.
- Смена всех паролей и ключей.
- Запрос перепроверки в Яндекс Вебмастере и Search Console.
- Регулярные обновления и копии вне хостинга.
Частые вопросы
Помогут ли плагины безопасности, если сайт уже заражён?
Они хорошо находят известные сигнатуры и изменённые файлы ядра, но не всегда находят код в базе и в своих файлах темы. Сканер — помощник, а не замена ручной проверке.
Нужно ли сообщать клиентам о взломе?
Если есть риск утечки персональных данных — да, и это требование законодательства о защите персональных данных. Если пострадал только внешний вид или были редиректы — достаточно исправить и закрыть причину.
Почему хостинг заблокировал сайт?
Обычно из-за рассылки спама или повышенной нагрузки от вредоносного кода. После очистки хостинг снимает блокировку по запросу.
Можно ли просто восстановить сайт из старой копии?
Можно, если копия точно сделана до заражения. Но точку входа всё равно нужно закрыть: уязвимый плагин или украденный пароль остаются, и через несколько дней сайт заразят снова.
Нужна помощь?
Если не хочется разбираться самому или не получилось — напишите мне. Посмотрю сайт и скажу, что сломалось и сколько стоит исправить.
