Видалення зараженого звичайного плагіна не гарантує, що 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 наявність malware?
Ні, окрема функція не є доказом. Легітимний код іноді декодує дані або використовує складні бібліотеки. Водночас поєднання таких функцій із прихованим отриманням параметрів, записом файлів, динамічним include чи зовнішнім керуванням є серйозною підставою для ізоляції та поглибленого аналізу.
Що робити, якщо підозрілий файл з’являється знову після видалення?
Це означає, що джерело persistence не знайдено або зловмисник досі має доступ. Перевірте cron, інші плагіни й теми, wp-config.php, облікові записи, SSH-ключі, права запису, логи та серверні процеси. Змініть секрети доступу й за потреби відновіть сайт із перевіреної чистої копії.
Висновок
Аудит MU-плагінів і drop-in-файлів має бути окремим етапом реагування на компрометацію WordPress. Перевірте інвентар, походження, метадані, код і хеші, а потім ізолюйте лише те, що підтверджено як небезпечне або не має легітимного пояснення.
Після очищення важливо не тільки відновити роботу сайту, а й переконатися, що файл не повертається, доступи відкликані, а логи не показують повторної активності. Такий підхід зменшує ризик повторного зараження й не руйнує необхідні механізми кешування без достатніх підстав.