Каждый месяц я вижу в отчётах хостингов одно и то же: сотни заблокированных попыток подбора пароля, десятки запросов к странным URL, попытки залить PHP-шелл через форму обратной связи. Это не атаки на банки — это рутина для обычных сайтов на Joomla, WordPress, OpenCart или «1С-Битрикс». Взламывают не потому, что вы кому-то интересны, а просто потому, что ваш сайт работает на PHP и на нём стоит плагин, который не обновляли с 2019 года.
Большинство владельцев думают, что безопасность — забота хостера или дорогих систем мониторинга. На деле 4 из 5 успешных взломов, которые я расследовал, происходили из-за трёх вещей: пароль admin/admin123, устаревший плагин галереи и отсутствие резервной копии. При этом неважно, на чём сделан сайт — фундаментальные принципы защиты едины для всего зоопарка PHP-движков. В этом материале я собрал то, что реально работает: от настройки сервера до ежемесячного чек-листа, без маркетинга и запугиваний.
Почему сайты на PHP-CMS так часто становятся мишенями?
PHP обслуживает около 75% всех динамических сайтов. Злоумышленникам не надо искать конкретную жертву — автоматические сканеры просто идут по списку доменов и пробуют типовые уязвимости. Когда я проверяю логи на своих проектах, то вижу сотни запросов в день: /wp-admin, /administrator, /bitrix/admin, /index.php?option=com_oldplugin&task=badfile. Это роботы, им всё равно, WordPress у вас или Joomla.
Масштаб проблемы и статистика
Открытый код популярных CMS даёт разработчикам возможность быстро править ошибки, но одновременно даёт хакерам карту уязвимостей. Модульная архитектура «ядро + расширения» делает защиту неравномерной: ядро Joomla или WordPress обычно аудируется пристально, а в плагине фотогалереи, скачанном с forum.joomla.org, может быть захардкоженный вызов eval(). По моим наблюдениям, в 2025–2026 годах именно через старые или непроверенные расширения проходила добрая половина компрометаций.
Что ещё усугубляет ситуацию:
- Отложенные обновления. Клиенты боятся, что после апдейта что-то сломается, и откладывают обновление на полгода. За это время известная уязвимость уже включена во все сканеры.
- Готовые инструменты взлома. SQL-карты, брутфорсеры, фаззеры — всё это есть в открытом доступе. Сегодня для атаки не нужно быть программистом, достаточно уметь запустить скрипт с инструкцией.
- Один хостинг — много сайтов. На виртуальном хостинге взлом одного сайта нередко открывает доступ ко всей учётной записи. Если у вас там же лежит тестовый поддомен с незакрытыми дырами, готовьтесь к проблемам.
Типичные сценарии взлома
Чтобы выстроить защиту, полезно понимать, как именно чаще всего проникают на сайт. За годы практики я сталкивался с этими векторами десятки раз:
- SQL-инъекция — подстановка SQL-кода в строку запроса. Если разработчик склеил запрос из пользовательского ввода, можно вытащить всю базу или записать в неё свои данные. На старых плагинах Joomla 1.5 такое встречалось сплошь и рядом.
- XSS (межсайтовый скриптинг) — внедрение JavaScript, который выполняется у посетителя. Через XSS угоняют сессии администраторов или подменяют формы ввода платёжных данных.
- Code Injection — прямая запись PHP-файла через уязвимую загрузку или eval(). Часто злоумышленник заливает шелл «wso.php» и получает файловый менеджер прямо на сервере.
- Брутфорс (подбор пароля) — автоматический перебор логинов и паролей. Если для входа используется стандартный admin, а пароль — дата рождения компании, взлом займёт минуты.
- Уязвимости в плагинах — старый плагин комментариев, слайдера или форм обратной связи, который уже не поддерживается автором. Именно такие модули я первым делом удаляю на аудите.
Фундаментальные принципы защиты: Архитектура и код
Никакой плагин безопасности не спасёт, если код позволяет подставлять что угодно в SQL-запросы. Поэтому начинать нужно с правильной архитектуры: разделение данных и запросов, экранирование вывода, запрет исполнения в пользовательских директориях. Если вы заказываете сайт, требуйте от разработчика именно эти базовые вещи.
1. Защита от SQL-инъекций
SQL-инъекция — это когда злоумышленник через поле ввода (поиск, логин, ID товара) передаёт фрагмент SQL. Если код строится как "SELECT * FROM users WHERE login='".$_GET['user']."'", то подставив admin' OR '1'='1, получим выборку всех записей. На практике я видел, как через плагин поиска для Joomla вытягивали хеши паролей за несколько запросов.
Единственно правильный способ — подготовленные выражения (Prepared Statements). Они разделяют структуру запроса и данные, так что никакое форматирование не превратит параметр в исполняемый код.
Пример безопасного подхода на PDO:
$query = $db->prepare("SELECT * FROM users WHERE login = :login");
$query->execute([':login' => $userInput]);
$result = $query->fetchAll();
Владельцу сайта нужно убедиться, что CMS и все установленные расширения используют PDO или хотя бы MySQLi с подготовленными запросами, а не старые mysql_query. Если в коде плагина встречается mysql_query — удаляйте его без сожалений.
2. Защита от XSS (Cross-Site Scripting)
XSS-атаки эксплуатируют неосторожный вывод пользовательских данных на страницу. Если поле «Имя» в комментариях не экранируется, туда можно вставить <script>alert('XSS')</script>, и скрипт выполнится у всех, кто откроет страницу.
Универсальное решение — экранирование вывода с помощью htmlspecialchars() в PHP или встроенных механизмов шаблонизаторов. В Joomla, например, при выводе через JHTML или com_content экранирование обычно уже есть, а в самописных шаблонах про него часто забывают.
Пример безопасного вывода:
echo htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');
Дополнительно рекомендую настроить Content Security Policy (CSP) — HTTP-заголовок, который ограничивает источники скриптов и стилей. Даже если злоумышленник найдёт способ вставить скрипт, браузер не выполнит код с чужого домена.
3. Защита от внедрения кода (Code Injection)
Самый опасный сценарий: через форму загрузки аватара или файла конфигурации злоумышленник записывает на сервер PHP-файл с обратным шеллом. Если хостинг позволяет выполнять PHP в папке /uploads, дальше он сможет делать что угодно.
Правила защиты, которые я настраиваю на всех проектах:
- Запретить выполнение PHP в пользовательских директориях. В .htaccess для Apache добавляем:
php_flag engine off <FilesMatch "\.php$"> Order Deny,Allow Deny from all </FilesMatch>Для Nginx аналогично — исключить обработку .php в location /uploads.
- Проверять MIME-тип и расширение при загрузке. Разрешать только .jpg, .png, .pdf и т.п. Никаких .pht, .phtml, .php5.
- Никогда не использовать eval(), include(), require() с данными от пользователя. Даже если кажется, что it безопасно, это красный флаг.
Многие CMS имеют встроенные механизмы: в WordPress функция wp_upload_bits() выполняет проверки, в Joomla — JFile::upload(). В любом случае полезно дополнительно защититься на уровне сервера.
4. Управление доступами и аутентификация
База из десяти администраторов со слабыми паролями — это не защита, а проходной двор. На одном из проектов клиент раздал доступы «всем менеджерам», в итоге логин admin и пароль 123456 держались полгода, пока сайт не стал рассылать спам.
Минимальный набор правил, который я требую от каждого клиента:
- Пароль минимум 12 символов, с буквами в обоих регистрах, цифрами и спецсимволами. Генератор паролей — ваш лучший друг.
- Двухфакторная аутентификация (2FA). Плагины типа Two Factor Authentication для Joomla и WordPress добавляют второй фактор — код из приложения или SMS. Даже если пароль утечёт, без телефона в админку не войти.
- Ограничение попыток входа. После 3–5 неудачных попыток IP-адрес блокируется на 15–30 минут. Это ломает любой автоматический перебор.
- Принцип минимальных привилегий. Редактору не нужны права администратора, менеджеру — установка плагинов. Используйте роли.
По своему опыту скажу: настройка 2FA и ограничения попыток закрывает 90% проблем с подбором паролей. Это занимает 10 минут, а пользу приносит годы.
Практический чек-лист безопасности для владельцев сайтов
Этот список я составлял на основе многократных аудитов сайтов на Joomla, WordPress, OpenCart и Битриксе. Пройдите по пунктам, отметьте выполненные и приведите оставшиеся в порядок. Чек-лист удобно обновлять раз в месяц.
Чек-лист: 20 шагов к безопасному сайту
| № | Действие | Выполнено? | Примечание |
|---|---|---|---|
| 1 | Обновление CMS: установлена последняя стабильная версия (WordPress, Joomla и т.д.) | Проверьте в разделе «Обновления» | |
| 2 | Обновление плагинов: все расширения актуальны, неиспользуемые удалены | Особое внимание тем, что не обновлялись > 2 лет | |
| 3 | Сложные пароли: у всех пользователей пароли от 12 символов, уникальные для сайта | Используйте менеджеры паролей | |
| 4 | 2FA: двухфакторная аутентификация включена для всех администраторов | Google Authenticator или аналоги | |
| 5 | Ограничение попыток входа: блокировка после 3–5 ошибок | Плагин типа Limit Login Attempts | |
| 6 | Ревизия пользователей: удалены неактивные учётки, права урезаны до необходимого минимума | Не забудьте про учётки бывших сотрудников | |
| 7 | Безопасные директории: в /uploads, /images, /temp запрещено выполнение PHP | .htaccess или конфиг Nginx | |
| 8 | Проверка файлов: нет посторонних .php, .phtml в пользовательских папках | Можно скриптом поиска | |
| 9 | Резервное копирование: автоматическое ежедневное создание дампов базы и файлов на внешнее хранилище | Akeeba Backup, UpdraftPlus | |
| 10 | Мониторинг целостности: настроена проверка изменений в ядре и файлах | Wordfence, Security Check | |
| 11 | Защита от SQL-инъекций: CMS и плагины используют подготовленные запросы | Проверить код критичных расширений | |
| 12 | Защита от XSS: вывод всегда экранирован | Особенно в комментариях, профилях | |
| 13 | Защита от Code Injection: отсутствуют eval() и небезопасные include с пользовательским вводом | Проверить кастомные скрипты | |
| 14 | CSP: заголовок Content-Security-Policy настроен | Хотя бы для скриптов и стилей | |
| 15 | Защита конфигов: wp-config.php, configuration.php недоступны извне | .htaccess с deny from all | |
| 16 | Изоляция БД: база слушает только localhost | В конфиге bind-address = 127.0.0.1 | |
| 17 | Антивирусная проверка: на сервере (если есть) или периодическая проверка десктопным сканером | ClamAV, AI-Bolit | |
| 18 | Регулярный аудит: полная проверка по чек-листу раз в месяц | Выделить час в календаре | |
| 19 | Обучение персонала: сотрудники знают базовые правила (не открывать подозрительные письма, не вводить пароли на чужих сайтах) | Провести 15-минутный инструктаж | |
| 20 | План реагирования: задокументировано, кто что делает при взломе, где лежат резервные копии и как откатить сайт | Достаточно простого текстового файла |
Пошаговая инструкция: Как защитить сайт от взлома
Это универсальная последовательность действий, которую я применяю при первичной настройке сайтов на любой PHP-CMS — от Joomla до Битрикса.
Шаг 1: Обновление системы и плагинов
Обновления закрывают известные дыры, поэтому это первое, с чего я начинаю. Важно: перед любым обновлением делайте резервную копию.
Порядок действий для популярных систем:
- WordPress: «Обновления» → обновить ядро, затем все плагины и темы. Неиспользуемые удалить.
- Joomla: «Система» → «Управление обновлениями» → обновить Joomla, затем через «Менеджер расширений» обновить все расширения.
- OpenCart / 1С-Битрикс: через встроенные разделы обновлений, предварительно проверив совместимость модулей.
Старая истина: если плагин не обновлялся больше двух лет, считайте его потенциально опасным и ищите альтернативу.
Шаг 2: Установка и настройка плагинов безопасности
Комплексные плагины закрывают сразу несколько слоёв защиты. Для WordPress я почти всегда ставлю Wordfence, для Joomla — Security Check в связке с Akeeba Backup. Настройка проста: после установки включаем все основные модули (брандмауэр, сканер файлов, защиту от брутфорса), настраиваем лимит попыток входа и обязательно подключаем 2FA.
Для WordPress:
- Wordfence Security — межсетевой экран, проверка файлов, 2FA.
- iThemes Security — хорош для быстрой настройки базовых защит.
- Two Factor Authentication — если нужна только двухфакторка.
Для Joomla:
- Akeeba Backup — резервное копирование.
- Two Factor Authentication — штатный плагин ядра для 2FA.
- Security Check — проверка базовой конфигурации.
После установки запустите первое сканирование и обязательно исправьте критические замечания.
Шаг 3: Настройка резервных копий
Правило трёх копий: одна локально (на сервере), вторая в облаке (Google Drive, Яндекс.Диск), третья где-то ещё. На практике обычно хватает автоматической ежедневной выгрузки на внешнее хранилище. Я предпочитаю Akeeba Backup для Joomla и UpdraftPlus для WordPress — они умеют отправлять архивы в Dropbox, S3 или на FTP.
Обязательно проверьте процедуру восстановления: разверните копию на тестовом поддомене и убедитесь, что всё работает. Нередко бывает, что плагин создаёт битый архив, и узнают об этом только когда сайт уже лежит.
Шаг 4: Проверка файлов и базы данных
Используйте встроенные сканеры из плагинов безопасности. Они ищут сигнатуры вредоносного кода (eval, base64_decode, странные iframe). Плюс я периодически вручную проверяю папки /uploads и /images на наличие .php-файлов. В базе тоже могут быть вставки — например, вредоносный JavaScript в контенте статей. Для Битрикса есть штатный модуль «Безопасность», который анализирует и файлы, и БД.
Шаг 5: Настройка сервера и безопасности
Даже если у вас виртуальный хостинг, через .htaccess или Nginx-правила можно многое исправить.
- Отключение PHP в медиа-папках: в .htaccess для Apache я добавляю
php_flag engine offи запрещаю доступ к .php файлам. Для Nginx — исключаю location из обработчика PHP.
- Запрет доступа к конфигурационным файлам: для wp-config.php, configuration.php и аналогичных ставим запрет через .htaccess:
<Files "wp-config.php"> Order Deny,Allow Deny from all </Files>Для Joomla аналогично с configuration.php.
- Запрет внешнего подключения к MySQL: в my.cnf убедитесь, что bind-address = 127.0.0.1. Тогда база слушает только локально.
- CSP-заголовок: в .htaccess можно добавить базовый Content-Security-Policy, который ограничит скрипты собственным доменом. Начинайте с report-only режима, чтобы не сломать сайт.
Шаг 6: Обучение и мониторинг
Технические меры бесполезны, если менеджер передаёт пароль по почте или устанавливает плагин с левого форума. Я прошу клиентов провести 15-минутный ликбез: не открывать вложения от незнакомцев, не вводить учётные данные на подозрительных страницах, использовать только официальные источники расширений.
Мониторинг: настройте уведомления о неудачных входах и изменениях файлов. Wordfence, Security Check или самописные скрипты пусть шлют письмо при попытке залить PHP-файл в uploads. И обязательно храните план реагирования: кому звонить, где лежат бэкапы, в какой последовательности восстанавливать сайт.
Типовые ошибки и как их избежать
Ниже — список граблей, на которые я сам наступал и которые регулярно вижу у клиентов.
Ошибка 1: Использование устаревших версий CMS и плагинов
Знаю случай, когда сайт на Joomla 2.5 висел до 2020 года, пока через известную уязвимость не залили фишинговые страницы. Если обновление невозможно, найдите способ мигрировать или хотя бы изолируйте сайт (выключите лишние расширения, закройте админку по IP). В общем же случае — только регулярные апдейты.
Ошибка 2: Слабые пароли
Пароль «12345678» или название компании с годом основания — это приглашение. Генератор паролей и менеджер решают проблему. Для админки обязательно включайте 2FA, чтобы даже при утечке пароль не дал доступа.
Ошибка 3: Установка плагинов без проверки
Плагин с тремя установками и последним обновлением в 2018 году — почти гарантированная дыра. Беру расширения только из официальных каталогов, смотрю активность разработчика, читаю changelog. Помню, как на одном Битриксе клиент поставил модуль «формы связи» с форума, и тот содержал встроенный шелл.
Ошибка 4: Отсутствие резервных копий
Самая простая и самая фатальная ошибка. Любое обновление, любой взлом — без бэкапа вы теряете всё. Автоматические ежедневные копии на внешнее хранилище — это минимум, который я настраиваю даже на самых простых сайтах.
Ошибка 5: Неверная настройка сервера
Открытые phpinfo(), доступ к .git и .env, возможность выполнить PHP в папке с картинками — всё это я встречаю регулярно. Проверьте директивы сервера прямо сейчас: если в /uploads лежит файл info.php, он не должен открываться.
Ошибка 6: Отсутствие мониторинга
Без мониторинга вы узнаете о взломе только когда Google пометит сайт как вредоносный или хостер заблокирует аккаунт за рассылку спама. Включите уведомления о подозрительной активности, хотя бы по email.
Инструменты и плагины для защиты сайта
Подборка проверенных решений для основных платформ. Бесплатные версии закрывают базовые потребности, платные дают расширенный функционал (вроде защиты от DDoS или централизованного управления).
Плагины для WordPress
| Плагин | Функции | Цена |
|---|---|---|
| Wordfence Security | Брандмауэр, сканер файлов, 2FA, защита от SQL-инъекций | Бесплатно / $199/год |
| iThemes Security | Защита входа, 2FA, мониторинг файлов | Бесплатно / $99/год |
| Two Factor Authentication | Лёгкий плагин только для включения 2FA | Бесплатно |
| Updraft Plus | Резервное копирование, восстановление | Бесплатно / $99/год |
| File Integrity Monitor | Отслеживание изменений файлов ядра | Бесплатно |
Плагины для Joomla
| Плагин | Функции | Цена |
|---|---|---|
| Akeeba Backup | Автоматические резервные копии в облако, восстановление | Бесплатно / $99/год |
| Two Factor Authentication | Встроенный плагин ядра для 2FA | Бесплатно |
| Security Check | Базовый аудит конфигурации безопасности | Бесплатно |
| Joomla Security Scanner | Сканирование файлов на вредоносный код | Бесплатно |
Плагины для OpenCart
| Плагин | Функции | Цена |
|---|---|---|
| Security Module | Брандмауэр, мониторинг файлов, 2FA | $99/год |
| Backup Module | Резервное копирование, восстановление | Бесплатно |
Плагины для 1С-Битрикс
| Плагин | Функции | Цена |
|---|---|---|
| Модуль «Резервное копирование» | Встроенное автоматическое резервное копирование | Встроенный |
| Модуль «Безопасность» | Брандмауэр, проактивная защита, 2FA, мониторинг | Встроенный |
Онлайн-сервисы для проверки безопасности
| Сервис | Функции | Цена |
|---|---|---|
| Sucuri SiteCheck | Сканирование на вредоносный код, проверка чёрных списков | Бесплатно |
| Google Safe Browsing | Статус сайта в базе Google, предупреждения о фишинге | Бесплатно |
| VirusTotal | Загрузка и проверка отдельных файлов десятками антивирусов | Бесплатно |
| SecurityTrails | Мониторинг DNS, сертификатов, истории IP | Бесплатно / $99/год |
Частые вопросы (FAQ)
1. Как часто нужно обновлять CMS и плагины?
Ядро и расширения я обновляю ежемесячно. Если выходит срочное обновление безопасности, ставлю его в течение суток. Главное правило: не держите расширение, которое не обновлялось больше двух лет — либо найдите альтернативу, либо удалите.
2. Что делать, если сайт был взломан?
Последовательность, которую я отработал: немедленно закройте сайт заглушкой (можно через .htaccess), снимите дамп базы и копию файлов для анализа. Запустите сканер (Wordfence, AI-Bolit) на заражённой копии. Удалите все посторонние файлы. Обновите CMS и все плагины до последних версий, смените пароли и сессионные ключи. Если есть чистый бэкап — разверните его, но предварительно выясните, как произошло проникновение, иначе взлом повторится. После восстановления обязательно настройте мониторинг.
3. Нужен ли антивирус для сайта?
Антивирус на сервере (ClamAV, AI-Bolit) может помочь обнаружить уже загруженный шелл, но это вторичный рубеж. Первичная защита — обновления, минимальные права, настройка сервера и плагин безопасности с брандмауэром. На виртуальном хостинге часто нет возможности поставить антивирус, так что упор делаем на профилактику.
4. Как защитить базу данных от взлома?
База должна принимать соединения только с localhost (bind-address = 127.0.0.1). Пароль пользователя БД должен быть уникальным и сложным, не root. В коде приложения обязательно используйте подготовленные запросы. Никогда не храните дампы базы в веб-доступных папках.
5. Что такое 2FA и зачем она нужна?
Двухфакторная аутентификация (2FA) добавляет второй фактор к паролю: код из приложения (Google Authenticator, Яндекс.Ключ) или SMS. Даже если пароль утечёт, войти без телефона не получится. Для любой админки я считаю 2FA обязательной.
6. Как проверить сайт на наличие вредоносных файлов?
Используйте плагины безопасности (Wordfence, Security Check, Joomla Security Scanner) — они умеют искать по сигнатурам. Дополнительно можно прогнать файлы через онлайн-сервисы типа Sucuri SiteCheck или загрузить подозрительные файлы на VirusTotal. Раз в месяц я вручную проверяю папки /uploads, /tmp, /cache на наличие .php-файлов, которым там не место.