☰
WORDPRESS / PRACTICE

Аудит MU-плагинов и drop-in-файлов после взлома WordPress

Аудит MU-плагинов и drop-in-файлов после взлома WordPress

Удаление заражённого обычного плагина не гарантирует, что WordPress очищен. Злоумышленник может оставить механизм повторного доступа — persistence — в каталоге wp-content/mu-plugins или в одном из drop-in-файлов, которые подключаются автоматически.

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

Что такое MU-плагины и drop-in-файлы

MU-плагины, или must-use plugins, обычно хранятся в wp-content/mu-plugins. WordPress загружает их автоматически, без обычной активации через административную панель. Это удобно для корпоративных политик, защитных проверок, пользовательских интеграций и хостинговых модулей, но одновременно делает каталог привлекательным для сокрытия вредоносного кода.

Drop-in — это специальный PHP-файл в wp-content, который WordPress или плагин использует вместо отдельного стандартного компонента. Чаще всего после инцидента проверяют advanced-cache.php, object-cache.php и db.php. Например, object-cache.php может быть частью Redis Object Cache, а advanced-cache.php — системы page cache. Само наличие такого файла не доказывает заражение.

В стандартном случае WordPress загружает PHP-файлы MU-плагинов из корня каталога mu-plugins. Файлы во вложенных каталогах могут не подключаться автоматически, однако их также следует проверить: легитимный MU-плагин может содержать основной файл в корне и дополнительный код ниже.

  • MU-плагины нельзя оценивать только по их наличию или отсутствию в панели управления.
  • Неизвестный файл со случайным именем, свежей датой изменения и обфусцированным кодом требует отдельного расследования.
  • Имя файла, время изменения и расположение являются сигналами для проверки, но не самостоятельным доказательством вредоносности.

Подготовьте безопасный аудит после инцидента

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

Если есть признаки активной атаки, смените пароли после первичного сбора доказательств: SSH, хостинг-панелей, SFTP, базы данных, аккаунтов WordPress и внешних сервисов. Также проверьте SSH-ключи, cron-задачи и доступы к CI/CD. Иначе злоумышленник может повторно записать уже очищенный файл.

Работайте от имени пользователя, у которого есть доступ к файлам, но не используйте root без необходимости. Копии подозрительных файлов храните за пределами web root и не запускайте их в браузере или через PHP.

  • Создайте отдельную копию заражённого состояния до внесения изменений.
  • Зафиксируйте домен, IP-адрес, часовой пояс сервера и примерное время обнаружения инцидента.
  • Не открывайте подозрительный PHP-файл через URL: даже простой просмотр может инициировать его выполнение.
  • Если сайт обрабатывает платежи или персональные данные, привлеките специалиста по incident response до удаления доказательств.

Соберите список MU-плагинов и drop-in-файлов

Начните с инвентаризации. Команда WP-CLI показывает MU-плагины, известные WordPress. Отдельно найдите drop-in-файлы в wp-content, поскольку они не являются обычными плагинами и анализируются другим способом.

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

  • Сравните список MU-плагинов с документацией хостинга, разработчиков и установленных систем кэширования.
  • Обратите внимание на файлы без понятного имени, комментария или соответствующего плагина.
  • Проверяйте не только три наиболее известных drop-in-файла, но и другие PHP-файлы непосредственно в wp-content.
wp plugin list --status=must-use

find wp-content/mu-plugins wp-content -maxdepth 1 \
  -type f \( -name 'advanced-cache.php' -o -name 'object-cache.php' -o -name 'db.php' \) -ls

find wp-content/mu-plugins -type f -name '*.php' -print

Проверьте метаданные, владельца и содержимое файлов

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

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

Особое внимание уделите eval, base64_decode, gzinflate, str_rot13, необычно длинным закодированным строкам, динамическим include или require, вызовам shell_exec, system, passthru, curl_exec и wp_remote_get к неизвестным доменам. Опасным сигналом также является код, который проверяет секретный GET-параметр, cookie или заголовок, а затем выполняет скрытое действие.

  • Сравните файл с чистой версией из официального пакета или репозитория, используя ту же версию.
  • Просмотрите первые и последние строки: вредоносный код часто добавляют в конец легитимного файла.
  • Проверьте PHP-файлы на наличие неоправданных прав записи.
  • Не считайте минимизированный или обфусцированный код автоматически вредоносным, но потребуйте подтверждения его происхождения.
stat wp-content/mu-plugins/*.php wp-content/advanced-cache.php \
  wp-content/object-cache.php wp-content/db.php 2>/dev/null

find wp-content/mu-plugins wp-content -maxdepth 1 -type f -name '*.php' \
  -printf '%M %u:%g %TY-%Tm-%Td %TH:%TM %p\n'

grep -RInE 'eval\s*\(|base64_decode|gzinflate|shell_exec|passthru|system\s*\(|assert\s*\(' \
  wp-content/mu-plugins wp-content/*.php 2>/dev/null

Отличите легитимный drop-in от вредоносного

Drop-in нужно проверять вместе с компонентом, который его установил. Выясните, используется ли Redis, page cache, object cache или другая инфраструктура, и соответствует ли файл документации этого компонента. Если плагин удалён, а drop-in остался, это может быть как корректный остаток после удаления, так и persistence.

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

Не заменяйте object-cache.php или advanced-cache.php вслепую. Удаление может отключить кэш, вызвать ошибки подключения к Redis или изменить поведение сайта. Перед изоляцией сохраните копию и согласуйте действие с ответственным за инфраструктуру.

  • Выясните, какой компонент создал файл и когда он был установлен или обновлён.
  • Проверьте, соответствуют ли подключения к Redis, Memcached или внешнему endpoint ожидаемой инфраструктуре.
  • Сравните хеш подозрительного файла с хешем заведомо чистой копии.
  • После замены проверьте вход в систему, кэширование, запись в базу данных, cron и критически важные формы.
sha256sum wp-content/mu-plugins/*.php \
  wp-content/advanced-cache.php wp-content/object-cache.php wp-content/db.php 2>/dev/null

wp core verify-checksums

Изолируйте подозрительный код и проверьте результат

Если файл имеет признаки компрометации, сначала переместите его в карантин за пределами web root или переименуйте, предварительно создав копию. Более безопасный вариант — восстановить чистый файл из проверенного источника, а не вручную удалять несколько подозрительных строк. Если происхождение drop-in неизвестно, временно отключите связанный механизм только после оценки последствий.

После изоляции просмотрите логи веб-сервера, PHP, WordPress и WAF. Ищите запросы к подозрительным endpoint, попытки записи в wp-content, POST-запросы к административным или неизвестным URL, ошибки подключения к внешним доменам и повторное появление файла.

Проверьте сайт из неавторизованной сессии, отдельно протестируйте административную панель и ключевые функции. Затем через некоторое время повторите инвентаризацию. Если файл вернулся, проблема, вероятно, осталась в другом плагине, аккаунте, cron, теме или серверном доступе.

  • Не удаляйте единственную копию подозрительного файла до завершения фиксации доказательств.
  • Проверьте, не появились ли новые PHP-файлы в uploads, cache, languages или временных каталогах.
  • Проверьте cron-задачи на уровне WordPress и сервера.
  • После очистки обновите ядро, темы и плагины из надёжных источников, а также отзовите скомпрометированные сессии и ключи.
find wp-content -type f -name '*.php' -printf '%TY-%Tm-%Td %TH:%TM %u:%g %p\n' \
  | sort

wp cron event list

# После изоляции просмотрите новые записи в соответствующих логах сервера и PHP.

Типичные ошибки во время аудита

Самая распространённая ошибка — считать, что список активных плагинов описывает весь исполняемый код WordPress. MU-плагины, drop-in-файлы, тема, wp-config.php и файлы в uploads могут оставаться без внимания.

Вторая ошибка — удалять все неизвестные файлы без проверки. Так можно сломать кэширование или потерять важные доказательства. Противоположная крайность — оставить подозрительный файл только потому, что сайт после взлома работает. Работоспособность не свидетельствует об отсутствии бэкдора.

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

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

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

Является ли каждый MU-плагин вредоносным?

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

Можно ли просто удалить advanced-cache.php или object-cache.php?

Не стоит. Файл может быть легитимной частью page cache или Redis. Сначала создайте копию, определите компонент-владелец, сравните файл с чистой версией и оцените последствия отключения. Если файл заражён, замените его проверенной чистой копией и протестируйте сайт.

Доказывают ли eval и base64_decode наличие вредоносного кода?

Нет, отдельная функция не является доказательством. Легитимный код иногда декодирует данные или использует сложные библиотеки. Однако сочетание таких функций со скрытым получением параметров, записью файлов, динамическим include или внешним управлением является серьёзным основанием для изоляции и углублённого анализа.

Что делать, если подозрительный файл появляется снова после удаления?

Это означает, что источник persistence не найден или злоумышленник по-прежнему имеет доступ. Проверьте cron, другие плагины и темы, wp-config.php, аккаунты, SSH-ключи, права записи, логи и серверные процессы. Смените секреты доступа и при необходимости восстановите сайт из проверенной чистой копии.

Вывод

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

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

← Все материалы WordPress