Безопасность CMS: 7 практик, которые спасут от взлома
Любая CMS удобна до первой компрометации. Хорошая новость: 80% атак блокируются несколькими дисциплинированными мерами. Ниже — практики, конфиги и чек-листы, которые снижают риск взлома, блокируют автоматические эксплойты и ускоряют восстановление, если что-то всё-таки пошло не так.
Введение: модель угроз для типичного сайта на CMS
Угроза №1 — массовые автоматические атаки по известным уязвимостям тем и плагинов. №2 — слабые пароли и повторное использование учётных данных. №3 — плохая конфигурация сервера: избыточные права, исполняемый PHP в /uploads, отсутствие WAF и логирования. Мы строим защиту по слоям: от кода CMS и плагинов — к веб-серверу, сети и резервным копиям.
- Поверхность атаки:админ-панель, формы, REST API, загрузки файлов, XML-RPC, cron.
- Векторы:SQLi, XSS, CSRF, LFI/RFI, brute force, уязвимые зависимости, poisoned plugin updates.
- Цели злоумышленника:спам/редиректы, бекдоры, кража БД, пивот в инфраструктуру.
Практика №1. Обновления ядра, плагинов и зависимостей
Большинство инцидентов — последствия неустановленных патчей. Обновления закрывают CVE, меняют алгоритмы хеширования, усиливают аутентификацию и очищают небезопасные API. Обновляем всё: ядро CMS, темы, плагины, composer/npm-зависимости, PHP и OpenSSL.
Процесс обновлений
- Прод/стейдж/локал. На стейдже автосборка, smoke-тест, затем релиз на прод.
- Снапшот БД и файлов перед обновлением.
- Лог изменений: что обновлено, версия, дата, ответственный.
- Мониторинг 24 часа после релиза (ошибки 5xx/4xx, скорость, аномалии в логах).
| Компонент | Периодичность | Инструмент | Примечание |
|---|---|---|---|
| Ядро CMS | ежемесячно/по security-релизу | встроенный updater | security-релизы — срочно |
| Плагины/темы | еженедельно | vendor dashboard | удалять заброшенные |
| PHP | раз в квартал | репозитории дистрибутива | только поддерживаемые ветки |
| Composer/npm | ежемесячно | composer audit, npm audit |
фикс CVE |
Практика №2. Минимальные привилегии и сегментация
Ни один сайт не должен работать от root. Привилегии — минимальные. Доступ — сегментирован. В панели CMS только нужные роли, в системе — отдельные пользователи для PHP-FPM, БД и деплоя.
Права файлов и каталогов
- Файлы:
0644, каталоги:0755, конфиги:0600. - В
/uploads: запрет исполнения PHP/CGI. - Отдельный пользователь для
php-fpmи владельца веб-контента.
Примеры конфигурации
Nginx: запрет PHP в /uploads
location ~* ^/uploads/.*\.(php|phar|phtml)${ return 403;}
location /uploads/{ autoindex off; add_header X-Content-Type-Options nosniff;}
.htaccess(Apache) — запрет исполнения
<Directory "uploads"> php_flag engine off RemoveHandler .php .phtml .php3 .php4 .php5 .php7 .phar <FilesMatch "\.(php|phar|phtml)$"> Require all denied </FilesMatch>
</Directory>
В БД создайте отдельного пользователя с SELECT/INSERT/UPDATE/DELETEи без DROP/ALTER, если CMS не требует миграций на проде.
Практика №3. Безопасная аутентификация: 2FA, пароли, ограничение доступа
Лучшая защита панели — сложные пароли + 2FA + ограничение по IP/стране. Брутфорс останавливается rate-limit и блокировками.
- Пароли: длина 12+, менеджер паролей, уникальные на каждого пользователя.
- 2FA: TOTP (Google Authenticator/Authy), резервные коды.
- Ограничение по IP: доступ в /admin только с белых списков.
- Блокировка по неудачным попыткам: Fail2Ban/WAF-правила.
Fail2Ban: фильтр для nginxauth
[nginx-auth]
enabled=true
port=http,https
filter=nginx-auth
logpath=/var/log/nginx/*error*.log
maxretry=5
bantime=3600
Отключите XML-RPC и стандартные «/xmlrpc.php» если CMS это поддерживает, либо ограничьте по IP.
Практика №4. Конфигурация сервера: HTTPS, HSTS, WAF, заголовки
HTTPS обязателен. Включаем HSTS, строгие политики контента и типы защиты в заголовках. В идеале — WAF на уровне веб-сервера или CDN. p>
Базовые security-заголовки
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
Content-Security-Policy (минимум)
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: https:;
script-src 'self' 'nonce-{{nonce}}' https:; style-src 'self' 'unsafe-inline' https:;
object-src 'none'; base-uri 'self'; frame-ancestors 'self'" always;
Для форм — включите SameSite=Laxдля cookies сессий, флаг Secureи HttpOnly.
mod_security / CRS (Apache/Nginx через ModSecurity)
Подключайте OWASP Core Rule Set. Включайте режим «anomaly scoring», а не жёсткий deny, чтобы видеть влияние на легитимный трафик.
Практика №5. Защита от SQLi, XSS и CSRF на уровне приложения
Любой пользовательский ввод — недоверенный. Применяем валидацию, экранирование, токены и параметризованные запросы.
- SQLi: только prepared statements/ORM, запрет конкатенации SQL.
- XSS: экранирование HTML, очистка WYSIWYG, CSP, запрещённый
innerHTMLдля пользовательских данных. - CSRF: токены в каждой POST-форме, проверка Origin/Referer.
- Загрузка файлов: проверка mime и расширения, перегенерация имени, хранение за пределами web-root, в идеале — на объектном хранилище.
Пример Nginx-фильтра от типичных payload
location /{ if ($query_string ~* "(union.*select|select.+from|concat\()"){ return 403;} if ($request_uri ~* "\.(bak|sql|swp|git|env)$"){ return 403;}}
Отключите опасные функции PHP: disable_functions=exec,passthru,shell_exec,system,proc_open,popen,show_source. Включите open_basedir, expose_php=Off.
Практика №6. Резервное копирование, контроль целостности и восстановление
Бэкапы — последняя линия защиты. Их отсутствие превращает любой инцидент в катастрофу. Стратегия 3–2–1: три копии, два типа носителей, одна — вне площадки.
Что бэкапить
- База данных (полные + инкрементальные).
- Каталоги приложения и
/uploads. - Конфиги веб-сервера,
php.ini,crontab, unit-файлы systemd. - Секреты: .env/ключи — в отдельном хранилище секретов.
График и хранение
- Снимки БД: ежедневно/каждые 6 часов для критичных систем.
- Файлы: ежедневно. Хранение 7–30 дней плюс ежемесячные — до 6–12 месяцев.
- Хранилище: S3-совместимое с версионированием и MFA-delete.
Проверка восстановления
Раз в квартал проводите тест восстановления на стейдже. Скрипт восстановления должен быть автоматизирован.
Контроль целостности
Используйте хеш-деревья или инструменты: Tripwire, AIDE, Wordfence/Bitrix Inspector. Настройте уведомления о любых изменениях в веб-корне вне процесса деплоя.
Практика №7. Наблюдаемость и реагирование: логи, алерты, playbook
Чем раньше замечаете инцидент, тем меньше ущерб. Без логов и алертов атаки обнаруживаются по жалобам пользователей и банам в поиске.
Что логировать
- Доступ и ошибки веб-сервера:
$remote_addr, UA, referrer,request_time, статус, размер ответа. - Авторизации, изменения ролей, изменения настроек, установки/удаления плагинов.
- Исключения приложения, медленные запросы БД.
Алерты
- Рост 4xx/5xx на X% за Y минут.
- Всплеск POST на /wp-login.php, /admin/, /xmlrpc.php.
- Изменения в веб-корне вне деплоя (inotify, hash-сканер).
Incident Response Playbook
- Изоляция: бэкап текущего состояния, перевод в режим readonly/maintenance.
- Сбор артефактов: логи, дампы, хеши изменённых файлов.
- Устранение: удаление бекдоров, патчи, ротация ключей/паролей.
- Восстановление: из чистого бэкапа + патчи.
- Постмортем: причина, точка входа, изменения в контролях.
Практика 7½. Сокращение поверхности атаки
- Удаляйте неиспользуемые плагины/темы и демо-файлы.
- Отключите directory listing:
autoindex off/Options -Indexes. - Скройте версию CMS в метатегах и HTTP-заголовках.
- Ограничьте доступ к
/wp-admin,/bitrix/,/administratorпо IP или через VPN.
Hardening для популярных CMS
WordPress
- Отключить
xmlrpc.phpили ограничить по IP. - Изменить префикс таблиц БД, отключить редактор файлов из панели:
define('DISALLOW_FILE_EDIT', true); - WAF-плагин (например, Wordfence) + ограничение логина по IP/2FA.
- Перенос
wp-config.phpза пределы web-root, salts — уникальные.
1C-Bitrix
- Включить «Проактивную защиту», ограничить административный раздел по IP/BasicAuth.
- Разнести
/uploadи запретить исполнение скриптов внутри. - Регулярные проверки «Монитор качества» и «Инспектор сайта».
Joomla/OpenCart/Drupal
- Обновления ядра и расширений, отключение неиспользуемых модулей.
- Расширения безопасности (2FA, firewalls), запрет PHP в media/.
- Проверка прав на конфиги и кэш-директории.
Чек-лист перед релизом и ежемесячная рутина
| Контроль | Статус | Комментарий |
|---|---|---|
| HTTPS/HSTS/CSP/заголовки | □ | минимальные политики включены |
| WAF/mod_security/CRS | □ | анализ ложных срабатываний |
| Отключён PHP в /uploads | □ | проверка 403 по тестовому .php |
| Права файлов/папок | □ | 0644/0755, конфиги 0600 |
| 2FA и ограничение по IP | □ | для всех админов |
| Удалены лишние плагины | □ | инвентаризация |
| Бэкапы и тест восстановления | □ | последний тест <=90 дней |
| Мониторинг и алерты | □ | пороговые значения настроены |
FAQ: частые вопросы о безопасности CMS
Достаточно ли одного WAF, чтобы сайт был безопасным?
Нет. WAF снижает риск, но не заменяет обновления, ограничение прав, 2FA и бэкапы. Используйте WAF как слой, а не «волшебную кнопку».
Нужно ли скрывать версию CMS?
Да, это снижает вероятность автоматических атак по сигнатурам. Но без обновлений скрытие версии не спасёт.
Что важнее: ежедневные бэкапы или жёсткие пароли?
И то и другое. Пароли уменьшают шанс инцидента, бэкапы уменьшают его последствия. Без одного из них система уязвима.
Можно ли безопасно использовать бесплатные плагины?
Да, если это официальные репозитории, у плагина понятный владелец, регулярные апдейты и нет негативных отчётов в CVE-базах.
Как быстро понять, что сайт скомпрометирован?
Смотрите аномалии в логах, рост 4xx/5xx, неожиданные редиректы, неизвестные файлы в веб-корне, предупреждения из Search Console/Вебмастера. Инструменты целостности оповестят о подмене файлов.
Итог
Безопасность CMS — это не разовая «настройка безопасности», а режим работы: регулярные обновления, минимальные права, сильная аутентификация, безопасная конфигурация сервера, защита от инъекций и XSS, бэкапы и мониторинг с планом реагирования. Эти семь практик снимают основной риск и превращают случайный инцидент из кризиса в рутинную операцию восстановления.