Як працює Nightward
Nightward - монітор безпеки WordPress, що працює під час роботи сайту. Він записує, що роблять встановлені плагіни й теми, називає файл і рядок, які за це відповідають, і звітує на пошту. Тут пояснено кожен монітор, що означає кожна знахідка і що з нею робити.
Встановлення
Вимоги
- WordPress 6.2 або новіший, PHP 7.4 або новіший. Підтримуються MySQL, MariaDB і інтеграція з базою SQLite.
- Робочий
wp_mail(). На більшості хостингів це означає SMTP-плагін. - WP-Cron, що запускається хоча б щогодини. Рекомендовано справжнє серверне cron-завдання, див. Планові завдання.
- Бажано, щоб тека
wp-content/mu-pluginsбула доступна для запису: тоді Nightward стартує раніше за інші плагіни.
Встановлення
- Завантажте
nightward-1.0.2.zip. - У WordPress відкрийте Плагіни → Додати → Завантажити плагін, оберіть zip і натисніть Встановити.
- Натисніть Активувати. В меню адмінки з'явиться пункт Nightward.
- Відкрийте Nightward → Налаштування, перевірте час звіту й отримувачів і натисніть Надіслати тестовий звіт.
Що відбувається під час активації
- Створюються три таблиці: події, вихідні хости й хеші файлів.
- Записується ранній завантажувач
wp-content/mu-plugins/0-nightward-early.php. Must-use плагіни завантажуються раніше за звичайні, тож Nightward бачить їхні хуки й запити з першого рядка. Файл видаляється при деактивації Nightward. - Плануються щоденний звіт, щогодинна перевірка й нічне обслуговування.
- Через хвилину стартує перше сканування цілісності. Воно фіксує поточний стан кожного пакета.
- Починається період навчання. Див. Перша доба.
Оновлення
Nightward розповсюджується з цього сайту, а не з WordPress.org. Щоб оновити, деактивуйте плагін, замініть теку nightward новою версією і активуйте знову. Події, еталони й налаштування зберігаються. Заміна файлів самого Nightward змінює його власний знімок, тому після оновлення запустіть Цілісність → Сканувати зараз і прийміть пакет Nightward, якщо він з'явиться в списку.
Вихідний код і вся історія змін - на GitHub. Там само можна повідомити про помилку через Issues.
Перша доба
Монітор, який повідомляє про звичайну поведінку кожного плагіна як про новину, марний. Перші 24 години (період навчання, змінюється в налаштуваннях) Nightward записує норму сайту, не повідомляючи про неї:
- з якими хостами зв'язується кожен плагін;
- які сторонні callback підключені до чутливих хуків;
- які є заплановані завдання;
- які файли є в кожному пакеті.
Критичні знахідки надходять з першої хвилини: код з eval() на хуку, адміністратор, створений анонімним запитом, запит до сервісу вставок. Екран «Огляд» показує, скільки лишилося до кінця навчання.
Повторне навчання після оновлень
Коли плагін чи тему встановлюють, активують або оновлюють через WordPress, вони отримують шість годин, протягом яких нові хуки записуються як новий еталон. Вони все одно з'являються в журналі (як Низький для хуків входу й видимості, Інфо для решти), тож новий плагін, що підключився до входу, буде видно в наступному звіті.
Події та рівні серйозності
Усі монітори пишуть в один журнал подій. У події є рівень, розділ, назва, пояснення і, де можливо, плагін чи тема, файл і рядок, які за неї відповідають.
Рівні
| Рівень | Значення | Миттєвий лист |
|---|---|---|
| Критичний | Ознаки зламу або зміна, що дає комусь контроль: прихований адміністратор, код з eval() на хуку входу, перехоплене оновлення, шкідливий код в uploads. | Так |
| Високий | Ймовірна проблема, але є легітимні пояснення: перевірка ліцензії з локальною відповіддю, файл змінився без зміни версії, відкритий debug-лог. | За бажанням |
| Середній | Варто перевірити: пакети оновлень по HTTP, дозволене виконання PHP в uploads, сайт без HTTPS. | Ні |
| Низький | Зміни, про які варто знати: плагін звернувся до нового хоста, вхід з нової мережі, оновлення поза WordPress. | Ні |
| Інфо | Записи для контексту: адміністратор, створений на екрані «Користувачі», новий еталон після оновлення. | Ні |
Статуси
| Статус | Що означає |
|---|---|
| Відкрита | Нова або повторилася після вирішення. Рахується на огляді і в лічильнику меню (лише критичні й високі). |
| Переглянута | Ви її бачили і працюєте над нею. Лишається в списку, але не вважається новою. |
| Вирішена | Виправлено. Якщо те саме станеться знову, подія відкриється і зможе знову надіслати сповіщення. |
| Ігнорується | Для цього сайту це очікувано. Про таку саму подію більше не повідомлятиметься. |
Дублікати
Одна й та сама знахідка зберігається один раз із лічильником. Плагін, що зробив той самий запит 500 разів, - це одна подія з × 500, і сповіщення по ній одне. Для файлових знахідок хеш файлу входить в ідентифікацію: якщо проігнорований файл знову зміниться, з'явиться нова подія.
Атрибуція
Знахідки називають відповідальний компонент: плагін чи тему за назвою, must-use плагін, drop-in на кшталт db.php, ядро WordPress або код, виконаний через eval(), якщо в коду немає файлу. Для подій під час роботи Nightward проходить стек викликів до першого кадру, що належить плагіну чи темі. Для callback хуків використовується reflection PHP, щоб знайти файл і рядок, де визначено функцію.
Події зберігаються незалежно від мови і показуються мовою того, хто їх читає, - в адмінці й у листах.
Вихідні запити
Кожен виклик через HTTP API WordPress (wp_remote_get(), wp_remote_post() і все, що на них побудовано) записується з хостом, плагіном, що його зробив, файлом і рядком виклику. Значення параметрів запиту видаляються перед збереженням, тож ліцензійні ключі й токени з URL не зберігаються.
Знахідки
| Знахідка | Рівень |
|---|---|
| Запит до сервісу вставок або анонімного обміну файлами (pastebin.com, paste.ee, transfer.sh, file.io…) | Критичний |
| Запит до тунелю (ngrok, швидкі тунелі Cloudflare, localtunnel…), сервісу перехоплення запитів (webhook.site, requestbin, pipedream), домену динамічного DNS, адреси .onion | Критичний |
| Запит до polyfill.io і пов'язаних доменів з атаки на ланцюг постачання 2024 року | Критичний |
| Запит до відомого розповсюджувача піратських плагінів | Критичний |
| Запит на публічну IP-адресу замість домену | Високий |
| Запит до Telegram Bot API або вебхука Discord | Середній |
| Плагін уперше звернувся до хоста (після періоду навчання) | Низький або Інфо для відомих сервісів |
Власні домени плагіна не вважаються новими хостами. Nightward бере їх із заголовків Plugin URI, Author URI і Update URI, ігноруючи платформи на кшталт GitHub, WordPress.org і CodeCanyon.
Довірені хости
Якщо знахідка очікувана, наприклад ваш власний плагін пересилає пошту в Telegram-бот, натисніть Довіряти в події або на екрані «Мережа», або додайте домен у Налаштування → Довірені хости. Запити й завантаження оновлень з довірених хостів у звіт не потрапляють.
Перехоплення HTTP
WordPress дозволяє будь-якому плагіну самому відповісти на HTTP-запит через фільтр pre_http_request. Тоді запит не виходить за межі сервера. Плагіни кешування й інструменти «вимкнути зовнішні запити» роблять це легітимно. Піратські плагіни так відповідають на власні перевірки ліцензії, а шкідливий код - ховає або підробляє інформацію про оновлення.
Nightward ставить мітку після кожного callback на pre_http_request. Коли з'являється відповідь, він точно знає, який callback її створив, навіть якщо кілька анонімних функцій мають однаковий пріоритет. Подія показує callback, файл і рядок, підроблений код статусу й початок підробленої відповіді.
| Знахідка | Рівень |
|---|---|
Запит заблоковано через WP_Error | Низький |
| Відповідь підмінено для звичайного запиту | Середній |
Перевірка ліцензії, активації, верифікації чи оновлення отримала відповідь 200 локально | Високий |
| API WordPress.org відповіло локально | Високий |
| Один callback підробив відповіді для трьох і більше доменів | Критичний |
Callback-перехоплювач створено через eval() | Критичний |

Чутливі хуки
Деякі хуки WordPress вирішують, хто увійшов, що дозволено користувачу, що бачить адміністратор і куди йдуть оновлення та пошта. Nightward запам'ятовує кожен сторонній callback на цих хуках і повідомляє про нові.
| Група | Хуки |
|---|---|
| Автентифікація та права | authenticate, wp_authenticate_user, determine_current_user, check_password, user_has_cap, map_meta_cap, rest_authentication_errors, application_password_is_api_request, auth_cookie_valid, wp_login |
| Що бачить адміністратор | all_plugins, pre_user_query, users_list_table_query_args, views_users, show_advanced_plugins, site_transient_update_plugins, site_transient_update_core |
| Оновлення, HTTP і пошта | upgrader_pre_download, upgrader_package_options, pre_set_site_transient_update_plugins, pre_set_site_transient_update_themes, http_request_args, pre_wp_mail, phpmailer_init, xmlrpc_methods |
| Знахідка | Рівень |
|---|---|
Callback на будь-якому хуку скомпільовано з рядка через eval() або create_function() | Критичний |
| Новий callback на хуку автентифікації чи видимості від плагіна, який нещодавно не встановлювали й не оновлювали | Високий |
| Новий callback з must-use плагіна, drop-in файлу чи невідомого розташування | Високий |
| Новий callback на хуку оновлень, HTTP чи пошти | Середній |
| Новий callback одразу після встановлення чи оновлення плагіна | Низький / Інфо |
Callback, створені через eval(), не мають файлу-джерела, тож файлові сканери їх не знаходять. Nightward показує файл і рядок, де було викликано eval(). Екран «Хуки й Cron» показує всі поточні сторонні callback на цих хуках. Сама присутність плагіна в списку - не проблема: плагіни безпеки, членства й SMTP мусять підключатися. Але кожен рядок ви маєте впізнавати.
Користувачі та права
Прихований адміністратор - найпоширеніший спосіб зберегти доступ до зламаного сайту. Nightward стежить за кожним шляхом до прав адміністратора.
| Знахідка | Рівень |
|---|---|
Адміністратора створено чи підвищено під час анонімного запиту, користувачем без права призначати ролі або кодом з eval() | Критичний |
| Адміністратор з'явився в базі без виклику будь-якої функції користувачів WordPress (прямий SQL), знайдено щогодинним аудитом | Критичний |
| Прихований адміністратор: є в базі, але немає у відфільтрованому списку користувачів | Критичний |
| Адміністратора створив плагін, поки адміністратор працював в адмінці (наприклад, редактор ролей) | Високий |
| Для адміністратора створено пароль застосунку | Середній, Високий, якщо не з екрана профілю |
| Пароль чи e-mail адміністратора змінено кодом плагіна | Середній, Критичний, якщо поточний користувач не має права редагувати користувачів |
| Адміністратора створено з WP-CLI | Середній |
| Адміністратор увійшов з мережі (/24 для IPv4, /48 для IPv6), якої раніше не було для цього акаунта | Низький |
| Адміністратора створив адміністратор на екрані «Користувачі» або через REST API | Інфо |
Паролі застосунків дають постійний доступ до REST і XML-RPC. Вони оминають двофакторний вхід і переживають зміну пароля, тож це тихий спосіб зберегти доступ. Якщо ви його не створювали, видаліть у профілі користувача.
Опції
Кілька налаштувань передають контроль над сайтом тому, хто їх змінить. Nightward записує, хто їх змінив і чи це сталося через екрани налаштувань.
| Знахідка | Рівень |
|---|---|
default_role змінено на адміністратора, редактора чи менеджера магазину | Критичний |
| Реєстрацію відкрито при привілейованій ролі за замовчуванням | Критичний |
Адресу сайту (siteurl, home) змінено поза екраном налаштувань | Критичний |
| Передплатник, покупець, учасник, автор або роль за замовчуванням отримали права адміністратора | Критичний |
| E-mail адміністратора змінено поза екраном налаштувань | Високий |
| Плагін активовано кодом, а не з екрана «Плагіни» чи WP-CLI | Високий |
| Активну тему змінено кодом | Високий |
| Плагін записує ту саму опцію на 60% і більше переглядів сторінок | Низький |
| Autoload-опції важать понад 800 КБ (понад 3 МБ - середній) | Низький / Середній |
Записи опцій перевіряються вибірково приблизно на одному перегляді з двадцяти на фронтенді й оцінюються щогодини після щонайменше 15 вибірок. Плагін, що пише в базу майже на кожному відвідуванні, марнує ресурси й ламає повносторінковий кеш. У ліцензійному коді це також може означати, що сайт «дзвонить додому» на кожному запиті.
Заплановані завдання
Шкідливий код часто повертається після чистки, бо заплановане завдання завантажує його знову. Щогодинна перевірка порівнює WP-Cron з відомим списком.
| Знахідка | Рівень |
|---|---|
| Аргументи завдання містять PHP-код, довгий base64-блок або URL на файл | Критичний |
| Ім'я завдання схоже на випадкове (hex-рядки, довгі імена без голосних і розділювачів) | Високий |
| Нове завдання, до якого в цьому запиті не підключено обробник | Низький |
| Нове завдання (після періоду навчання) | Інфо |
Екран «Хуки й Cron» показує кожне завдання з розкладом, наступним запуском і плагіном, чия функція його виконує. Завдання без обробника зазвичай лишаються від видалених плагінів.
Цілісність файлів
Кожен файл коду (PHP, JavaScript, .htaccess, .user.ini, JSON, Twig) в ядрі, плагінах і темах порівнюється з еталоном.
| Пакет | Еталон |
|---|---|
| Ядро WordPress | Офіційні контрольні суми з api.wordpress.org для вашої версії й локалі. |
| Плагіни з WordPress.org | Офіційні контрольні суми версії з downloads.wordpress.org. |
| Преміум-плагіни й усі теми | Власний знімок Nightward, зроблений під час першого сканування кожної версії («Власний знімок»). |
| Знахідка | Рівень |
|---|---|
Змінений чи неочікуваний PHP-файл з ознаками шкідливого коду: eval(base64_decode(, дані запиту в eval/system, preg_replace /e, віддалений include, довгі base64-блоки, ланцюжки chr(), PHP у заголовку зображення | Критичний |
| Файл ядра відрізняється від релізу або невідомий файл серед файлів ядра | Високий |
| Файл плагіна з WordPress.org відрізняється від офіційної копії цієї версії або невідомий PHP-файл у ньому | Високий |
| Файл преміум-плагіна чи теми змінився або додано новий PHP-файл, а номер версії лишився тим самим | Високий |
| Версію пакета змінено поза оновлювачем WordPress (FTP, SSH, деплой) | Низький |
| Файли видалено без зміни версії | Низький |
Як іде сканування
Сканування запускається щоночі (о 03:30 за замовчуванням) і після кожного оновлення, порціями по 400 файлів через WP-Cron, тож воно завершується навіть на шаред-хостингу. Цілісність → Сканувати зараз запускає його з браузера з індикатором прогресу. Коли відновлений файл знову збігається з еталоном, його подія закривається автоматично.
Прийняття власних змін
Якщо ви самі змінили преміум-плагін чи тему, перегляньте знахідку й натисніть Прийняти поточні файли для цього пакета. Поточні файли стануть новим еталоном, а відкриті події цілісності по ньому закриються.
Виконувані файли
Перевіряються щогодини (швидкий прохід) і щоночі (повний прохід).
| Де | Що потрапляє у звіт | Рівень |
|---|---|---|
uploads | PHP та інші виконувані скрипти; .user.ini / php.ini; .htaccess, що вмикає обробники скриптів чи налаштування PHP; медіафайли з PHP-кодом | Високий, Критичний з ознаками шкідливого коду |
uploads | Подвійні розширення на кшталт photo.php.jpg | Середній |
Корінь wp-content | PHP-файли, що не є drop-in файлами WordPress чи відомими конфігураціями кешу | Високий |
mu-plugins | Нові must-use плагіни (після періоду навчання) | Високий |
cache, languages | Виконуваний PHP (файли перекладів .l10n.php і файли даних кешу пропускаються) | Високий |
upgrade | PHP, що лишився після перерваних оновлень | Середній |
Файли даних, у яких першим рядком стоїть exit чи die, нічого не можуть виконати і в звіт не потрапляють. Так зберігають дані Sucuri, Wordfence і кілька плагінів кешу. Заглушки index.php «Silence is golden» теж пропускаються. Коли файл зі звіту видаляють, його подія закривається при наступному проході.
Канал оновлень
Nightward перевіряє, звідки приходять оновлення: і ті, що чекають у Майстерня → Оновлення (щогодини), і кожен пакет, який оновлювач справді завантажує.
| Знахідка | Рівень | Завантаження |
|---|---|---|
| Оновлення плагіна з WordPress.org чи ядра роздає інший сервер | Критичний | Завжди блокується |
| Пакет з відомого шкідливого хоста (сервіси вставок, тунелі, піратські розповсюджувачі) | Критичний | Завжди блокується |
| Пакет з хоста, не пов'язаного з розробником, або з голої IP-адреси | Середній | Блокується, якщо ввімкнено налаштування |
| Пакет завантажується через звичайний HTTP | Середній | Дозволено |
Запис у списку оновлень без обов'язкового поля plugin | Середній | - |
Хост пакета вважається нормальним, якщо це власний домен плагіна, довірений хост або поширена платформа розповсюдження (GitHub, Amazon S3 і CloudFront, Freemius, Envato, WooCommerce тощо). Знахідки щодо оновлень, які очікують, перелічують плагіни й теми, що можуть переписувати список оновлень, - тож відомо, де шукати.
plugin. WordPress.org таких записів не створює. Починаючи з версії 1.0.2, Nightward повідомляє про це і показує код, що змінює список оновлень. Зазвичай джерело - вбудований оновлювач плагіна з неофіційного джерела.Захищеність
Перевіряється щоночі й на вимогу з Захищеність → Запустити перевірку. Там, де це важливо, перевірка запитує файл ззовні через loopback-запит, так, як це зробив би зловмисник. Події створюються лише для проваленої перевірки. Оцінка починається зі 100 і втрачає бали за кожну провалену перевірку чи попередження залежно від рівня.
| Перевірка | Коли провалюється |
|---|---|
| Відкриті файли | debug.log (або ваш WP_DEBUG_LOG), .env, .git/HEAD, копії wp-config.php (.bak, .old, .save, .orig, ~, .txt, .swp), дампи SQL і архіви в корені сайту, якщо їх можна завантажити |
| Виконання PHP в uploads | Nightward записує нешкідливий тестовий файл в uploads, запитує його і видаляє. Якщо він виконався, будь-яка вразливість завантаження файлів стає виконанням коду. |
| Перегляд вмісту тек | Тека uploads показує сторінку «Index of». |
| XML-RPC | xmlrpc.php відповідає на методи входу (багато спроб пароля в одному запиті). |
| Перелік користувачів | REST API показує відвідувачам логіни користувачів. |
| Логін «admin» | Одного з адміністраторів звуть admin. |
| HTTPS | Адреса сайту не HTTPS. |
| Заголовки безпеки | Немає X-Content-Type-Options, X-Frame-Options чи CSP frame-ancestors, Referrer-Policy, а на HTTPS-сайтах - HSTS. |
| Права на wp-config.php | Запис дозволено всім або читання дозволено іншим користувачам сервера. |
| Редактор файлів | Не задано DISALLOW_FILE_EDIT. |
| Показ помилок | Помилки PHP показуються відвідувачам. |
| Версії PHP і WordPress | PHP старіший за 8.1 або доступне оновлення WordPress. |
| Неактивні плагіни | Деактивовані плагіни лишаються на диску, де їхні файли можна запитати напряму. |
| WP-Cron | Щогодинне завдання Nightward не запускалося понад три години. |
# wp-config.php
define( 'DISALLOW_FILE_EDIT', true );
define( 'WP_DEBUG_DISPLAY', false );
# nginx: заборонити PHP в uploads
location ~* /wp-content/uploads/.*\.php$ { deny all; }
# Apache (.htaccess у wp-content/uploads)
<FilesMatch "\.php$">
Require all denied
</FilesMatch>
Звіти та сповіщення
Щоденний звіт
Надсилається щодня в заданий час за часовим поясом сайту (о 20:00 за замовчуванням). Розклад перераховується після кожного звіту, тож він не зсувається при переході на літній час. Звіт містить:
- загальний стан і лічильники за рівнями за період від попереднього звіту;
- критичні й високі знахідки з джерелом, файлом і поясненням, далі інші знахідки коротко;
- нові вихідні адреси і плагіни, що до них зверталися;
- стан перевірок: останнє сканування цілісності, кількість хостів і підроблених відповідей, оцінка захищеності, стан WP-Cron.
З увімкненим Надсилати звіт, навіть якщо нічого не сталося (за замовчуванням) спокійний день теж дає короткий лист «Усе чисто». Якщо він перестав приходити, зупинився сайт, WP-Cron, доставка пошти або сам Nightward.
Миттєві сповіщення
Критичні знахідки (за бажанням і високі) надсилаються в момент виявлення, з усіма деталями й посиланням на подію. За замовчуванням - не більше 5 сповіщень на годину. Усе понад ліміт збирається в один лист, що надсилається по закінченню години.
Мова
Якщо перший отримувач - користувач сайту, звіт пишеться його мовою в WordPress. Інакше - мовою сайту. Українська й англійська є в комплекті.
Перевірка та доставка
Надіслати тестовий звіт одразу надсилає поточний звіт з позначкою тесту. Попередній перегляд відкриває його в браузері. Листи надсилаються через wp_mail() як HTML з текстовою частиною, тож нормально читаються й тоді, коли міст у Telegram чи Slack перетворює їх на текст. Якщо тест не пройшов, огляд покаже помилку поштового модуля; налаштуйте SMTP-плагін.

Адмінка
| Екран | Для чого |
|---|---|
| Огляд | Стан сайту, відкриті знахідки за рівнями, критичні й високі пункти, розклад звітів і стан пошти, картка кожного монітора і що Nightward не бачить. |
| Події | Повний журнал із фільтрами за рівнем, розділом і статусом, пошуком за назвою, файлом чи плагіном, масовою зміною статусу й розгорнутими деталями. |
| Мережа | Код, підключений до pre_http_request, і кожен хост за 30 днів з плагіном, кількістю запитів, підроблених відповідей і помилок. |
| Хуки й Cron | Сторонні callback на чутливих хуках за групами і всі заплановані завдання з обробниками. |
| Цілісність | Останнє сканування, кожен пакет з тим, з чим його звіряють, і його відкритими проблемами, Сканувати зараз і Прийняти поточні файли. |
| Захищеність | Перевірки з результатами, виправленнями й оцінкою і Запустити перевірку. |
| Налаштування | Усі опції, див. нижче. |
У меню адмінки є лічильник відкритих критичних і високих подій. Для екранів Nightward потрібне право manage_options.
Довідник налаштувань
| Налаштування | За замовчуванням | Примітки |
|---|---|---|
| Надсилати щоденний звіт безпеки | Увімкнено | |
| Час | 20:00 | Часовий пояс сайту (Налаштування → Загальні). |
| Отримувачі | E-mail адміністратора сайту | Список через кому. |
| Надсилати звіт, навіть якщо нічого не сталося | Увімкнено | Рекомендовано. |
| Миттєві сповіщення | Увімкнено | |
| Сповіщати про | Лише критичні | Або критичні й високі. |
| Максимум сповіщень на годину | 5 | Від 1 до 50. Решта об'єднується. |
| Монітори | Усі увімкнено | Кожен з дев'яти перемикачів повністю вимикає монітор. |
| Блокувати оновлення з непов'язаних хостів | Вимкнено | Перехоплені оновлення з WordPress.org і шкідливі хости блокуються завжди. |
| Запускатися раніше за інші плагіни | Увімкнено | Записує або видаляє must-use завантажувач. |
| Довірені хости | Порожньо | Один домен на рядок; домен другого рівня покриває свої піддомени. |
| Час щоденного сканування | 03:30 | Цілісність, повний прохід uploads, захищеність, перевірка autoload, очищення. |
| Файлів за порцію | 400 | Від 50 до 3000. Зменште на дуже повільному хостингу. |
| Період навчання, годин | 24 | Від 0 до 168. |
| Зберігати вирішені події, днів | 60 | Від 7 до 365. |
Планові завдання
| Завдання | Коли | Що робить |
|---|---|---|
nightward_daily_report | Час звіту | Надсилає щоденний звіт і планує наступний. |
nightward_hourly | Щогодини | Заплановані завдання, швидкий прохід uploads, оновлення, що очікують, аудит адміністраторів, оцінка записів опцій, самоперевірка розкладу звіту. |
nightward_daily_maintenance | Час щоденного сканування | Сканування цілісності, повний прохід uploads, перевірки захищеності, перевірка autoload, очищення старих подій. |
nightward_integrity_step | За потреби | Наступна порція сканування цілісності. |
nightward_instant_retry | За потреби | Надсилає сповіщення, відкладені через ліміт на годину. |
WP-Cron запускається лише тоді, коли сайт хтось відвідує. На сайтах з малою відвідуваністю або з кешем сторінок використовуйте справжній cron:
# wp-config.php
define( 'DISABLE_WP_CRON', true );
# crontab: кожні 5 хвилин
*/5 * * * * curl -s https://example.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1
# або через WP-CLI
*/5 * * * * cd /path/to/site && wp cron event run --due-now --quiet
Вирішення проблем
Листи не приходять
Натисніть Надіслати тестовий звіт. Якщо огляд показує помилку пошти, не працює wp_mail(): встановіть і налаштуйте SMTP-плагін. Якщо тест приходить, а щоденний звіт ні, не запускається WP-Cron; див. Планові завдання.
Звіт приходить із запізненням
WP-Cron чекає на відвідування. Налаштуйте справжній cron. Крім того, Nightward щогодини перевіряє, що звіт заплановано, і відновлює розклад, якщо він загубився.
Багато подій «новий хост» після встановлення плагіна
Новий плагін звертається до своїх сервісів. Довіряйте знайомим хостам одним кліком або додайте їх у «Довірені хости».
У звіт потрапила моя власна правка плагіна
Так і працює перевірка цілісності. Натисніть Прийняти поточні файли для пакета на екрані «Цілісність».
У звіт потрапив файл іншого сервісу безпеки
Деякі сервіси кладуть файли-конектори в корінь сайту, наприклад bv_connector_<hash>.php, який створюють MalCare і BlogVault. Відкрийте файл і переконайтеся, що він належить сервісу, яким ви користуєтесь. Далі видаліть його, якщо сервісу він більше не потрібен, або позначте подію як «Ігнорувати». Проігнорований файл знову потрапить у звіт, лише якщо зміниться.
Перевірки захищеності пропускаються
Сайт не може звернутися сам до себе (loopback). Часто це обмеження файрвола чи хостингу. «Здоров'я сайту» в WordPress теж потребує loopback; попросіть хостинг дозволити запити сервера до власного домену.
Цілісність показує «очікує першого сканування»
Перше сканування стартує через WP-Cron. Запустіть його кнопкою Цілісність → Сканувати зараз.
Швидкодія і приватність
Що коштує кожен перегляд сторінки
- Трасування стеку робиться лише тоді, коли сайт робить вихідний HTTP-запит.
- Перевірка хуків порівнює коротку сигнатуру з однієї невеликої autoload-опції. Повне порівняння запускається, лише коли набір callback змінюється.
- Записи опцій перевіряються вибірково приблизно на одному перегляді з двадцяти на фронтенді.
- Повний пошук callback з
eval()запускається приблизно на одному запиті з сорока. - Події записуються одним проходом у кінці запиту. Лише критичні записуються одразу.
- Сканування файлів, аудити й перевірки захищеності йдуть у фоні.
Приватність
У Nightward немає акаунта, телеметрії чи зовнішнього сервісу. Він звертається лише до api.wordpress.org і downloads.wordpress.org по контрольні суми та до вашого сайту для перевірок захищеності. У збережених URL значення параметрів видаляються. Звіти йдуть через wp_mail() вашого сайту. IP-адреси входів адміністраторів зберігаються як мережі (/24 або /48) в метаданих користувача, не більше 15 останніх.
Для розробників
Кожна нова або повторно відкрита подія викликає action, через який знахідки можна переслати деінде:
add_action( 'nightward_event', function ( array $event ) {
// ключі $event: id, module, type, severity, title, details,
// component, file, line, fingerprint
if ( 'critical' === $event['severity'] ) {
// надіслати в Slack, Telegram, збирач логів...
}
} );
Ідентифікатори модулів: outbound, interception, hooks, privilege, options, cron, integrity, uploads, update_channel, hardening, system.
Loopback-запити Nightward мають заголовок X-Nightward-Probe і не враховуються в статистиці вихідних запитів.
Переклади
Текстовий домен - nightward. Шаблон - languages/nightward.pot. Переклади також можна покласти в wp-content/languages/plugins/nightward-{locale}.mo.
Збережені дані та видалення
| Де | Що |
|---|---|
{prefix}nightward_events | Журнал подій. |
{prefix}nightward_egress | Вихідні хости за плагінами з лічильниками. Зберігаються 180 днів після останнього звернення. |
{prefix}nightward_files | Хеші SHA-256 пакетів із власним знімком. |
Опції nightward_* | Налаштування, еталони, стан сканування, стан звітів. |
Метадані користувача nightward_known_nets | Мережі, з яких входили адміністратори. |
mu-plugins/0-nightward-early.php | Ранній завантажувач. |
Вирішені, переглянуті й проігноровані події, а також низькі й інфо видаляються після строку зберігання. Деактивація Nightward прибирає завантажувач і планові завдання, а дані лишає. Видалення з екрана «Плагіни» прибирає таблиці, опції, transient-и, метадані користувачів, завантажувач і планові завдання.
Межі
- Запити через «сирий» cURL, сокети чи
file_get_contents()оминають HTTP API WordPress і не записуються. - Код, що виконується раніше за Nightward, під час роботи не відстежується:
wp-config.php, drop-in файли на кшталтdb.phpіobject-cache.php, must-use плагіни, що завантажуються раніше за0-nightward-early.php. Цілісність їхніх файлів усе одно перевіряється, де є еталон. - Прямі зміни в базі знаходить щогодинний аудит, без файлу, який їх зробив.
- Преміум-плагіни й теми вважаються довіреними в стані першого сканування.
- Nightward - не файрвол. Він не блокує відвідувачів і не шукає сигнатури шкідливого коду. Той, хто має доступ до сервера, може вимкнути будь-який плагін, тому відсутній щоденний звіт - уже тривога.
- Зроблено і протестовано для окремих сайтів. Активація на всю мережу працює, але звіти й налаштування не розділені за сайтами.
Список змін
- 1.0.2 ·
- Файли даних, що починаються з
exit(Sucuri, Wordfence, плагіни кешу), більше не вважаються виконуваними скриптами в uploads. Відкриті події по них закриваються автоматично. - Нове: записи в списку оновлень без поля
pluginпотрапляють у звіт разом із кодом, що може змінювати список. Саме вони дають попередження «Undefined property: stdClass::$plugin» на сторінці Плагіни → Додати.
- Файли даних, що починаються з
- 1.0.1 ·
- Довірені хости також прибирають знахідки щодо Telegram і Discord. Кнопка «Довіряти» з'являється в таких подіях.
- Листи лишаються читабельними, коли міст перетворює їх на текст.
- 1.0.0 ·
- Перший реліз: десять моніторів, щоденний звіт і миттєві сповіщення, українська й англійська.