Перейти к содержимому
Эльдар Шахвалиев
Обсудить проект
← Все проекты
202606.2026 — presentВ продеполный цикл

Сеть WordPress-сайтов наркологической клиники «От запоя»

Наркологическая клиника (бренд «Станция здоровья», Нижегородская обл.; сеть сайтов «От запоя») · Медицина / наркология (вывод из запоя, лечение алкоголизма и наркомании)

Fullstack-разработчик WordPress (соло): аудит кодовой базы и БД, оценка безопасности, доработки на проде

Сеть сайтов наркологической клиники: аудит, оценка безопасности и 22 доработки — всё на живом сайте, без тестовой копии и без права обновлять компоненты.

  • PHP
  • WordPress
  • Elementor
  • MySQL
  • JavaScript
  • CSS/SCSS
  • WP-CLI
  • Nginx
  • WPForms
  • Contact Form 7
  • TablePress
  • Redux Framework
  • WooCommerce
  • Slider Revolution
  • Max Mega Menu
  • Playwright
22
пунктов ТЗ обработано (доработки на двух сайтах)
7
пунктов безопасности (S1–S7) с приоритизацией и митигейтами без обновления
CVE-2025-62047, CVSS 9.9
критическая дыра (Arbitrary File Upload, уровень Subscriber) в case-addons 1.2.0 — выявлена и доказана
2 + 2
два рабочих WordPress-сайта (отдельные БД, не Multisite) + два домена-301-редиректа
1223
замены доменных ссылок при тиражировании на dzerzhinsk (wp search-replace, п.19)
5
параллельных web-research агентов в фазе исследования стека
  • Нашёл в установленном расширении критическую уязвимость 9.9 из 10: пользователь с минимальными правами мог загрузить на сервер любой файл и получить контроль над сайтами.
  • Уязвимость доказана по официальным базам, а не по выводу сканера; ложные срабатывания сканера отсеял отдельно.
  • Собрал план устранения из семи пунктов с оценкой сложности каждого — чтобы владелец выбирал очерёдность сам, не нарушая свой запрет на обновления.
  • Весь свой код положил в одно место, переживающее обновления темы, вместо правок в саму тему, как делали до меня.
  • Перенёс сделанное на второй сайт сети: у него отдельная база и другой движок форм, потребовалось 1223 замены ссылок.

Задача

У сети сайтов наркологической клиники накопился список из 22 доработок: навигация, формы заявок, прайс, поведение на телефонах, переделка первого экрана.

Сложность была не в самих правках, а в условиях. Сайты собраны на купленной готовой теме, история изменений не ведётся, тестовой копии нет, а обновлять компоненты владелец запретил — политика проекта. Любая правка идёт сразу на живой сайт, который принимает обращения людей.

Что сделано

  • Начал с разведки, ничего не меняя: из чего собраны сайты, где физически лежит содержимое страниц, какие расширения установлены и что о них известно в базах уязвимостей. Каждый вывод — с доказательством: файл и строка, запрос к базе или ответ сервера с датой.
  • Обнаружил в одном из установленных расширений критическую уязвимость: зарегистрированный пользователь с минимальными правами мог загрузить на сервер произвольный файл — то есть получить контроль над сетью сайтов клиники. Проверил по официальным базам, а не по выводу сканера, и отдельно отсеял ложные срабатывания.
  • Собрал план устранения из семи пунктов с оценкой сложности каждого — так, чтобы владелец мог выбрать очерёдность сам и не нарушить собственный запрет на обновления.
  • Обработал 22 пункта задания поэтапно. Перед каждым — резервная копия базы и файлов, к каждому — заранее описанный откат.
  • Весь свой код положил в одно место, которое переживает обновления темы, вместо правок в саму тему, как делали до меня. Любую доработку можно отключить одним движением.
  • Перенёс сделанное на второй сайт сети. Копированием это не решалось: отдельная база, другой движок форм — потребовалось 1223 замены ссылок.

Итог

Было

  • Правки шли прямо в купленную тему; ни истории изменений, ни тестовой копии
  • В установленных расширениях — незакрытая критическая уязвимость, обновления запрещены политикой
  • Второй сайт сети правился отдельно и вручную

Стало

  • Весь код в одном месте, переживающем обновления темы; каждая правка обратима
  • Уязвимость найдена и доказана, план устранения передан владельцу
  • Сделанное перенесено на второй сайт, различия движков учтены

Главная находка — критическая уязвимость в расширении темы, 9.9 балла из 10 по международной шкале: пользователь с минимальными правами мог загрузить на сервер произвольный файл и получить контроль над сетью сайтов клиники. Дыра найдена и доказана до того, как ею воспользовались; владелец получил план устранения из семи пунктов с оценкой сложности каждого.

Все 22 пункта задания обработаны, каждый — с резервной копией и готовым откатом; оба сайта сети работают. Три пункта ждут материалов от заказчика: фотографию врача, изображения вместо заглушек и цифры для блока преимуществ.

Технические детали

Решение и подход

  • CSS/PHP вне темы через mu-plugin. План изначально предлагал дочернюю тему medigo-child, но по решению заказчика выбран mu-plugin otz-custom.php — переживает обновления Medigo и не несёт риска сброса опций темы дочерней темой. В репозитории дочерней темы нет — подтверждает выбранный механизм (источник: sites/./themes/, docs/handoff.md).
  • Контент в БД, а не в файлах. Ключевая находка аудита: шапка/подвал — не Theme Builder и не хардкод, а CPT темы pxl-template, назначаемые опциями Redux (header_layout=3530, footer_layout=97); меню рендерит виджет темы pxl_menu, а не Max Mega Menu (это изменило способ правок навигации). Большинство задач — правки контента/настроек в БД на проде.
  • Прайс-лист переписан с сохранением единого источника данных: цены остаются в TablePress (заказчик правит привычно), а вывод — современные строки-карточки «услуга + цена-пилюля» через собственный шорткод, парсящий таблицу; DataTables отключён.
  • Hero первого экрана перерисован вручную (светлый дизайн), с настоящим тегом <h1> (закрывает и SEO-пункт H1/H2), аккуратной интеграцией с прозрачной overlay-шапкой темы (position:absolute) и полным набором адаптивных брейкпоинтов.
  • Прод-дисциплина: фронт — nginx с микрокэшем (не LiteSpeed на edge); после правок _elementor_data обязателен wp elementor flush-css; проверка через cache-buster и Playwright; SSH с учётом гео-блокировки порта 22 и троттлинга парольного входа (укрупнение батчей).

Стек и обоснование

WordPress + Elementor + тема Medigo/case-addons — унаследованный стек (выбор сделан до проекта). MySQL 8.0 (Percona), PHP 8.2, WP-CLI 2.8.1, фронт nginx/1.30 с микрокэшем. Формы: WPForms (главный) и Contact Form 7 (dzerzhinsk) — разные движки, правки переносились раздельно. Прайс — TablePress. Кастом — PHP/CSS в mu-plugin (без сборочного тулинга: ни package.json/composer.json для кастома, ни CI, ни тестов — фронт собирается Elementor'ом). Визуальная регрессия — Playwright (headless Chromium). Выбор инструментов продиктован запретом на обновления и отсутствием staging: решения подбирались совместимыми с текущими (часто устаревшими) версиями и максимально обратимыми.

Инженерные вызовы

  • Прод без сети и без отката-by-design: нет git и staging — компенсировано бэкапами БД/файлов перед каждой сессией, снимками _elementor_data перед патчем, точечными обратимыми правками и cache-flush-дисциплиной.
  • Контент в БД, а не в коде: правки приходилось локализовать в Elementor JSON и опциях Redux/плагинов, опровергая ошибочные исходные предположения (логотип, расположение копирайта, рендер меню темой pxl_menu, а не Max Mega Menu).
  • Две инсталляции с раздельными БД и разными движками форм — тиражирование шаблонов/контента и search-replace ссылок без авто-синхронизации.
  • Юридический контур РФ: наркология подпадает под ФЗ-38 ст.24 (обязательный дисклеймер «Имеются противопоказания…», раскрытие лицензии, запрет гарантий излечения и отзывов о выздоровлении; штраф юрлицу) и 152-ФЗ по ПДн пациентов из форм — это влияло на весь контент.

Безопасность (ключевая компетенция)

Отдельно оформленная экспертиза, выделенная заказчику в коммерческое предложение доп. работ (docs/reports/2026-06-18-security-additional-works.md):

  • Выявлены и доказаны критические уязвимости активного стека: case-addons 1.2.0CVE-2025-62047, CVSS 9.9 (Arbitrary File Upload уровнем Subscriber ≈ RCE на прод-сети клиники, bundled-плагин темы без авто-апдейта); Slider Revolution 6.7.34CVE-2025-9217 LFI (чтение wp-config.php с доступами к БД) +2 CVE; XSS в LiteSpeed Cache 7.7 на dzerzhinsk; рассинхрон Elementor Pro 3.27.4 ↔ core 3.34.1; EOL PHP 8.2 (31.12.2026). Каждый вывод перепроверен по первоисточникам (NVD/Patchstack/WPScan/вендор) с датами; отмечены ложные срабатывания сканеров (WooCommerce 10.4.4, woo-variation-swatches).
  • Приоритизация и митигейты без обновления: план S1–S7 со «сложностью» под расчёт стоимости, экономикой WAF (платный WAF Timeweb — клиент не подключает), снижением attack surface (удаление неиспользуемых WooCommerce/Slider Revolution), компенсациями (отключение открытой регистрации, аудит ролей Contributor+, 2FA).
  • Ответственное обращение с доступом и данными: аудит сервера — строго read-only; ПДн пациентов (wp_wpforms_entries) не выгружались и не попадали в отчёты (152-ФЗ); секреты (SSH-доступы в docs/credentials.md) не извлекались и не публиковались; предусмотрена ротация доступов после работ.
  • аудит
  • аудит безопасности
  • доработка существующего
  • прод-операции (SSH/WP-CLI)
  • SEO
  • 152-ФЗ/ПДн
  • контент
  • юридическое соответствие (ФЗ-38)