
Платный плагин «бесплатно» ставится за минуту и первое время работает как обещано: слайдер крутится, конструктор собирает страницы, окно про лицензионный ключ молчит. А месяца через три в подвале появляются ссылки на посторонние сайты, часть посетителей с телефонов уезжает на чужой домен, в индексе всплывают страницы, которых никто не создавал, и в Яндекс Вебмастере загорается метка о том, что сайт может угрожать безопасности. Плагин при этом продолжает исправно крутить слайдер.
Ниже — чем закладка отличается от вируса, что проверить в архиве до установки, какие места в WordPress я открываю первыми и что делать, если находка подтвердилась. Из инструментов — файловый менеджер хостинга, WP-CLI и панель вебмастера.
Почему «бесплатная» копия платного плагина — вопрос доверия, а не лицензии
Обстоятельство, которое сбивает с толку почти всех: WordPress распространяется под лицензией GPL, и производные работы — темы и плагины, использующие его код, — по общему правилу наследуют её условия. Поэтому код большинства коммерческих продуктов открыт, и платят не за право им пользоваться, а за обновления, поддержку и ключ. Отсюда вывод «лицензия свободная, значит качать можно откуда угодно».
Вывод неверный, но по другой причине. Копия со стороннего склада отличается от копии от автора не юридическим статусом, а тем, чего в ней нет:
- Эталона для сверки. У плагинов из каталога wordpress.org есть контрольные суммы, у произвольного архива сравнивать не с чем.
- Канала обновлений. Сборка без ключа не обновляется, и через год на сайте живёт код с публично описанными уязвимостями.
- Адресата претензий. Автор за этот архив не отвечает, склад не отвечает ни за что, а отвечает владелец сайта — в том числе перед посетителями.
Спор, выходит, не о лицензии, а о доверии: плагин в WordPress не «дополнение», а часть системы с правами ядра.
О юридической стороне — коротко и с оговоркой, что я SEO-специалист, а не юрист: редакции статей меняются, это повод открыть действующий текст закона. Права на программы регулирует часть четвёртая Гражданского кодекса от 18.12.2006 № 230-ФЗ: статья 1229 (исключительным правом распоряжается правообладатель, а свободная лицензия и есть форма разрешения), статья 1270 (способы использования, включая раздачу архива в интернете), статья 1301 (компенсация, размеры — по действующей редакции). Претензии авторов чаще касаются не кода под GPL, а сопутствующего: обхода проверки ключа и использования названия в чужой раздаче.
Отдельная строка — уголовная: статья 273 УК РФ от 13.06.1996 № 63-ФЗ говорит о вредоносных программах как о самостоятельном составе. Если в сборке окажется закладка и сайт начнёт участвовать в чужих делах, разговор перестанет быть спором о лицензии на плагин.
Чем закладка отличается от вируса и от обычной уязвимости
Уязвимость — ошибка автора: живёт до обновления и закрывается обновлением. Вирус или веб-шелл появляется после взлома и шумит: сайт тормозит, хостинг присылает письмо о нагрузке. Такой код сильно запутан, и именно его находят бесплатные сканеры — он давно попал в базы подписей.
Закладку положил человек, собиравший архив, сознательно и заранее, и задача её не сломать сайт, а долго и тихо им пользоваться. Отсюда свойства:
- Сайт работает нормально, ошибок нет — повода лезть в код нет.
- Код короткий, встроен в легальный файл темы и похож на обычную функцию оформления.
- Срабатывает выборочно: не для администратора, иногда только для робота или мобильных.
- Часто с отсрочкой: первые недели ничего не происходит, и к моменту активации никто не связывает проблему с плагином.
- Обновление не помогает: обновить такую сборку — значит найти следующую такую же.
Поэтому находят её через SEO, а не через безопасность: сначала падают позиции или всплывает метка в панели вебмастера, и только потом кто-то доходит до файлов темы.
Что закладка делает на практике и как это видно снаружи
Скрытые ссылки в подвале и шаблонах — блок нулевым размером шрифта, за границей экрана или только для робота. Сайт становится продавцом ссылок, а размещение SEO-ссылок названо отдельным нарушением в разделе «Диагностика → Безопасность и нарушения» Яндекс Вебмастера. Свои исходящие видно в коде страницы, а странных доноров — при разборе профиля: как смотреть бесплатно, я описывал в материале как проверить обратные ссылки на сайт.
Подмена содержимого и условный редирект. Робот получает страницу с чужими ссылками, посетитель — обычную; либо уводят только с мобильных или пришедших из поиска. Владелец с рабочего компьютера видит порядок, а в Вебмастере появляется запись про обманные редиректы. Доверие к сайту при этом обнуляется целиком.
Спам-страницы. Сотни сгенерированных страниц под чужие темы попадают в индекс и размывают тематику домена. Рядом близкий сценарий, когда наоборот, ваш контент выкладывают у себя: сайт клонировали на другом домене.
Рассылка писем с домена. Узнают чаще так: письма перестали доходить, домен попал в спам-листы, и вместе с мусором не доходят уведомления о заявках — подробнее о том, почему письма с сайта уходят в спам.
Ещё три сценария: скрытый администратор — чтобы вернуться после чистки файлов; реклама поверх сайта только для неавторизованных, поэтому владелец её не видит, а поведение людей видит поисковик; обращения к другим сайтам, заметные по нагрузке на хостинге.
| Признак на сайте | Что скорее всего происходит | Где искать в файлах |
|---|---|---|
| В коде страницы ссылки на незнакомые домены, в браузере их не видно | скрытые ссылки для робота | footer.php, header.php, functions.php |
| Страница для робота не совпадает со страницей для посетителя | клоакинг | условия по строке браузера в теме и mu-plugins |
| С телефона из поиска открывается чужой сайт | условный редирект | .htaccess, index.php темы, PHP в uploads |
| В индексе страницы на чужие темы | генерация спам-страниц | таблица опций, задания Cron |
| Письма не доходят, хостер пишет про рассылку | почтовый ретранслятор | очередь Cron, PHP вне структуры |
| Администратор, которого вы не создавали | оставленный вход | таблицы пользователей |
| Метка об угрозе в Вебмастере | поисковик нашёл опасный код | шаблоны темы, внешние скрипты |
Как проверить архив до установки
Источник. Безопасных три: каталог wordpress.org, сайт автора, официальный маркетплейс. Остальное — архив неизвестного происхождения. Если у продукта есть бесплатная версия в каталоге, сравните общие файлы построчно.
Контрольные суммы. В WP-CLI есть wp core verify-checksums для ядра и wp plugin verify-checksums для плагинов из каталога: они сравнивают файлы с эталоном wordpress.org и показывают изменённые и лишние. Для сборки со стороны эталона нет — и это уже ответ.
Список файлов смотрите, не распаковывая архив. Настораживает:
- PHP в папке картинок или скрипт среди переводов — файлы вне обычной структуры.
- Несоответствие расширения содержимому: имя от картинки, внутри — код.
- Минифицированный PHP: для JavaScript это норма, для PHP выигрыша нет.
- Аномально длинные строки: в нормальном коде строк в тысячи знаков нет.
- Расхождение дат: все файлы трёхлетние, один от прошлого месяца; вложенные архивы, особенно под паролем.
Текстовым файлам не верьте. readme.txt, заголовок плагина, номер версии, имя автора — текст, который правится в блокноте за пять секунд. Он не подтверждает ни версию, ни происхождение, ни целостность.
Какие конструкции в коде должны насторожить при чтении
Оговорка, без которой список бесполезен: каждая конструкция бывает законной, половина встречается в уважаемых библиотеках. Индикатор — не функция, а контекст: непонятно, зачем она здесь, результат сразу идёт на исполнение, данные приходят снаружи без проверки.
| Конструкция | Легальное применение | Когда это красный флаг |
|---|---|---|
eval, assert, create_function |
почти нигде, изредка в старых шаблонизаторах | всегда повод прочитать файл целиком |
base64_decode, gzinflate, str_rot13 |
вложения писем, картинка в виде строки | результат сразу исполняется, вход — длинная непонятная строка |
preg_replace с модификатором /e |
устаревший приём, в новых версиях PHP не работает | практически всегда |
system, exec, shell_exec, passthru |
обработка изображений, архивы | в теме и плагине оформления им делать нечего |
file_get_contents к внешнему адресу, curl_exec |
обращение к API, проверка лицензии | домен незнакомый, адрес собран из частей строки |
$_REQUEST, $_COOKIE в неожиданных местах |
формы, настройки, выбор устройства | чтение параметра в файле оформления, проверка на отсутствие куки |
| Имя функции из частей строки, длинные шестнадцатеричные литералы | динамические вызовы, ключи, бинарные данные | имя или адрес собираются так, чтобы не нашлись поиском по файлам |
| Условия по строке браузера робота | адаптация вывода | от условия зависит состав ссылок или содержимое |
Правило простое: настораживает не одна конструкция, а связка «данные снаружи или длинная строка → преобразование → исполнение». Видно цепочку целиком — дальше читать не нужно, нужно менять источник плагина.
Где в WordPress прячутся закладки
Мест немного, и они повторяются из случая в случай. Эту таблицу я использую как маршрутный лист — сверху вниз, ничего не пропуская.
| Место | Чего там быть не должно | Чем проверить |
|---|---|---|
functions.php темы |
работы с запросом, внешних обращений, кода в самом конце | прочитать целиком до последней строки |
Подвал, шапка, index.php темы |
вставок не по вёрстке, подключений неизвестных файлов | сравнить папку с оригиналом от автора |
wp-content/mu-plugins |
ничего, если вы туда не класли | эти файлы работают всегда и не видны в списке |
wp-content/uploads |
ни одного PHP-файла | find wp-content/uploads -name '*.php' |
wp-config.php, все .htaccess |
посторонних подключений, условной переадресации | сверить с образцом, прочитать вложенные .htaccess |
| Опции с автозагрузкой, задания WP-Cron | больших значений без владельца, заданий не от ядра и не от плагинов | wp option list --autoload=on, wp cron event list |
| Пользователи и роли | лишних администраторов, расширенных прав | wp user list --role=administrator |
| Файлы ядра | изменений и лишних файлов | wp core verify-checksums |
languages, кэш, архивы в корне |
PHP среди переводов и временных файлов | поиск PHP по папкам, сверка дат |
Порядок проверки уже работающего сайта
Если сборка со стороны уже стоит, порядок такой — платных инструментов не требует, занимает вечер.
- Снимите копию файлов и базы: по ней потом видно, что изменилось.
- Сверьте ядро и плагины по контрольным суммам: список изменённых и лишних файлов — точка входа.
- Найдите свежие правки:
find . -name '*.php' -mtime -30. Сайт не правили, а файлы менялись — разбирайтесь, кто их менял. - Сравните папку темы с оригиналом, а для сборки со стороны — читайте её файлы.
- Проверьте PHP там, где его быть не должно — в загрузках и кэше.
- Посмотрите пользователей и роли: права обычных ролей иногда расширяют, а список администраторов при этом чистый.
- Проверьте расписание Cron и опции с автозагрузкой: непонятное задание раз в час восстанавливает удалённый код, а опции читаются на каждой странице.
- Сравните код страницы для робота и для мобильного посетителя: расхождение в составе ссылок или переадресация — главный симптом. Заодно прогоните адреса на корректность кодов ответа.
- Прочитайте журналы: журнал доступа покажет обращения к незнакомым файлам, а журнал входов в админку — кто и откуда заходил.
- Проверьте почту: очередь отправки и репутацию домена.
- Откройте Вебмастер: раздел безопасности и нарушений покажет метку, статистика страниц в поиске — всплеск их числа.
И почти всегда повторяется одна методическая ошибка: проверяют из своего браузера, под своей авторизацией, с рабочего компьютера — в таких условиях закладка для неавторизованных мобильных посетителей себя не покажет.
Нашли закладку: что делать по шагам
Частая ошибка — начать с удаления найденного файла: код восстановится заданием Cron или через оставленного пользователя, и выйдет иллюзия чистого сайта.
| Шаг | Инструмент | Критерий, что шаг закрыт |
|---|---|---|
| 1. Закрыть доступ и снять копию для разбора | панель хостинга, дамп базы | сессии сброшены, копия лежит вне сайта |
| 2. Сменить пароли и ключи | хостинг, FTP, база, соли в wp-config.php |
после замены солей все разлогинены |
| 3. Поставить официальные версии | каталог wordpress.org, сайт автора | сверка сумм без расхождений |
| 4. Вычистить остальные места | маршрутный лист выше | в загрузках нет PHP, mu-plugins пуста |
| 5. Убрать лишних пользователей | wp user list, настройки ролей |
каждый администратор опознан |
| 6. Проверить бэкапы | те же проверки на каждой копии | найдена копия без закладки |
| 7. Убрать спам-страницы | карта сайта, вебмастер | отдают код «удалено», сняты с индексации |
| 8. Снять метку у поисковика | Вебмастер, раздел безопасности | метка снята, страницы на переобходе |
| 9. Завести регулярную проверку | сверка сумм, журнал входов | идёт по расписанию, а не когда вспомнили |
Про бэкапы отдельно: закладка лежала в файлах с первого дня, значит, есть во всех копиях после установки, и восстановление «из последней» возвращает сайт вместе с ней. Нужна копия до установки сборки, а если такой нет — чистые тема и плагины из официальных источников, в которые переносят контент.
Доступы считайте скомпрометированными все — и подрядчиков тоже; как их раздавать и отзывать, разобрано в материале про доступы к сайту. Если работа выходит за рамки «удалить файл и переставить плагин», дешевле обсудить порядок на SEO-консультации, чем менять всё разом.
Чем заменить платный плагин
Нужна одна функция из большого платного плагина. Чаще всего в каталоге есть бесплатный плагин, который делает именно её и делает лучше, потому что занимается только ей.
Функция нужна, но не критична. Половина того, что ставят «чтобы было», не используется, а каждый лишний плагин — ещё один автор, которому вы доверяете исполнение кода.
Функция нужна и стоит денег. Тогда одна честная лицензия вместо пяти сомнительных сборок; цены сверяйте с сайтом разработчика. Считать надо не цену лицензии, а вечер чистки плюс просадку трафика на время снятия метки.
На что я смотрю на странице плагина в каталоге: дата последнего обновления (не обновлялся годами — набор незакрытых уязвимостей), заявленная совместимость с актуальной версией WordPress, число активных установок, ответы автора в ветках вопросов, открытый репозиторий, разумный объём прав.
Если нужной функции нет ни в каталоге, ни у авторов, остаётся вариант, о котором забывают: небольшая доработка сайта под задачу. Двадцать строк в дочерней теме часто заменяют плагин на сотню файлов.
Почему антивирусный плагин не заменяет проверку
Сканер хорошо ловит известное: его сила — база подписей и эвристика по обфускации, то есть запутанный код и типовые веб-шеллы. Аккуратная закладка выглядит иначе: пять строк читаемого PHP внутри файла темы, которая уникальна и с эталоном не сравнивается. Формально запрещённого в них нет — получить значение, сравнить, вывести блок. Что блок содержит чужие ссылки и показывается только роботу, видно смыслом, а не подписью.
Второе ограничение: сканер-плагин работает внутри того же WordPress, который проверяет, а проверка снаружи — сверка сумм, чтение файлов через SSH, журналы — такого недостатка не имеет. Отсюда порядок: сначала чистая сборка из официального источника, затем ручная проверка по маршрутному листу, и только потом сканер — как страховка от известного, а не доказательство чистоты.
Что происходит с позициями после чистки и в каком порядке возвращать
Метка об угрозе безопасности. Пока она стоит, рядом с сайтом в выдаче показывается предупреждение, и переходы падают резко. Позиции обычно остаются на месте — страдает не место, а количество переходов с него. Поэтому важна скорость: чем раньше устранена причина и запрошена перепроверка, тем меньше потеря.
Спам в индексе и ссылки на чужие сайты. Тяжелее: пересматривается отношение к домену целиком, и возврат занимает месяцы — надо дождаться переоценки по новому состоянию.
Порядок возврата я выстраиваю так:
- Техника: чистая сборка, снятая метка, корректные коды ответа. Пока причина жива, остальное бессмысленно.
- Индекс: спам-страницы отдают код об удалении и уходят из карты сайта, нужные — на переобход, одним заходом.
- Ссылки: убрать посторонние исходящие и проверить входящие с мусорных площадок.
- Содержание: восстановить пострадавшие при чистке страницы; если материалы потеряны, проще заказать SEO-статьи заново, чем собирать обрывки из кэша.
- И только потом обычная работа: в таком порядке я строю SEO-продвижение сайта после чистки от вирусов — сперва доказать поисковику, что сайт стал другим, затем наращивать запросы.
По срокам: быстрее возвращаются сайты, где причину устранили целиком за один заход. Дольше всех — где чистили по частям: удалили файл, через неделю вернулось, потом нашли пользователя. Каждый цикл поисковик видит как новое ухудшение.
Коротко
- Спор о «платном плагине бесплатно» — не про лицензию: темы и плагины идут под GPL, но у копии со стороны нет ни сверки с эталоном, ни обновлений, ни ответственного за содержимое.
- Юридическая часть — ГК РФ от 18.12.2006 № 230-ФЗ (ст. 1229, 1270, 1301), уголовный риск — ст. 273 УК РФ от 13.06.1996 № 63-ФЗ, в действующей редакции.
- Закладка не вирус и не уязвимость: её кладут сознательно, она не ломает сайт и работает выборочно — потому живёт месяцами.
- До установки: только официальный источник, сверка через
wp core verify-checksumsиwp plugin verify-checksums, просмотр списка файлов.readme.txtи заголовок плагина не доказывают ничего. - В коде настораживают исполнение собранных строк, декодирование с запуском, системные команды, обращения к внешним адресам и чтение параметров запроса в файлах оформления.
- Маршрут проверки: файлы темы,
mu-plugins, PHP в загрузках,wp-config.php, все.htaccess, автозагружаемые опции, Cron, пользователи, файлы ядра. - После находки: закрыть доступ, сменить пароли и соли, поставить официальные версии, вычистить остальное — и лишь потом бэкап, потому что закладка есть и в нём.
- Возврат: техника и снятие метки, удаление спам-страниц, ссылки и содержание, и лишь потом продвижение — чистка по частям растягивает его сильнее всего.
Увеличьте позиции и продажи вашего сайта
Профессиональное SEO-продвижение с гарантией результата. Выберите подходящую услугу:
Остались вопросы по продвижению?
Меня зовут Анатолий Кузнецов, я SEO-оптимизатор с 20-летним стажем. Разберу ваш сайт, отвечу на вопросы и подскажу, что улучшить для роста позиций в Яндексе и Google.
Связаться со мной →
Комментарии
Игорь
Нашёл в подвале блок ссылок на четыре незнакомых сайта. Удалил строку из footer.php, через десять дней вернулась. Откуда она берётся, не понимаю: остальные файлы вроде чистые.
Анатолий Кузнецов автор
Возвращается — значит есть чему возвращать. Смотрите по порядку: задания Cron, папку обязательных плагинов, автозагружаемые опции. Обычно там сидит код, который раз в сутки дописывает строку обратно. И проверьте администраторов: если вход остался, чистить файлы можно бесконечно.
Наталья
Не согласна с тональностью. Мы пять лет ставим такие сборки клиентам, проблем не было ни разу. Может, страхи раздуты?
Анатолий Кузнецов автор
Вопрос в том, как вы узнали бы, что случай был. Ни один сценарий не даёт ошибки на экране: скрытые ссылки видны только в коде, подмена — при запросе от лица робота. Проверьте два пункта: код страницы с подменённой строкой браузера и поиск PHP в загрузках.
Павел
Поиск PHP в загрузках дал три файла с именами вроде системных. Сайту четыре года, туда никто ничего не заливал.
Елена
Тема у меня платная, купленная у автора. Команда сверки не работает: пишет, что темы нет в каталоге. Как тогда проверять?
Анатолий Кузнецов автор
Для товара вне каталога эталон вы делаете сами: скачайте архив из личного кабинета автора, посчитайте суммы файлов и храните список отдельно от сайта. И держите правки в дочерней теме: тогда расхождение в родительской папке означает, что менял её не вы.
Сергей
А если запретить исполнение PHP в загрузках на уровне сервера? Тогда любой файл там будет мёртвым.
Анатолий Кузнецов автор
Мера полезная, но она закрывает один путь — прямое обращение к файлу по адресу. Код, подключаемый из темы или плагина, исполнится всё равно: запускает его сам WordPress. И само появление файла там, где его быть не должно, важнее возможности его открыть.
Дмитрий
Про бэкапы в точку. Откатились на месяц назад, через две недели всё вернулось. Дошло только тогда: проблема приехала ещё в марте вместе с темой.
Марина
Метку получили в пятницу вечером, заметили в понедельник по обвалу переходов. Позиции остались, просто по ним никто не шёл. После перепроверки сняли за пару дней.
Антон
Не понимаю пункта про сканер. У меня он стоит и каждый день пишет «угроз не найдено». Получается, ему нельзя верить?
Анатолий Кузнецов автор
Верить можно тому, что он говорит, и нельзя — тому, чего он не говорит. «Угроз не найдено» значит «совпадений с подписями нет», а не «постороннего кода нет». Добавьте сверку контрольных сумм ядра раз в месяц и просмотр кода главной от лица робота.
Владимир
Добавлю индикатор из своего опыта: файл темы на несколько сотен килобайт, когда соседние по двадцать. Открыл — внутри одна строка на весь файл. Это видно даже без чтения кода.
Оксана
А как проверять архив, если есть только файловый менеджер хостинга? Половина команд мне недоступна.
Руслан
Про доступы подрядчиков отдельное спасибо. После чистки выяснилось: администраторов семь, трое не работают с сайтом два года. Права никто не отзывал, просто забыли.
Алексей
Подтверждаю мысль про отказ от лишнего. Пересобрал сайт с двадцати восьми плагинов до одиннадцати, выкинув всё, что стояло «на будущее». Грузится быстрее, и поводов для беспокойства меньше.