Защита сайта на Joomla от взлома: 5 слоёв обороны и уязвимости 2026

Защита сайта на Joomla: пять слоёв обороны от взлома
Пять слоёв защиты Joomla: резервные копии, обновления, доступ, сканирование и серверная защита.

Если сайт на Joomla уже взломан или появились подозрительные файлы, не ограничивайтесь обновлением расширений. Сначала остановите повторный вход, сохраните копию для проверки, затем очистите файлы и базу данных, смените доступы и настройте защиту веб-сервера. Ниже, понятная последовательность действий с пояснениями, какой код и куда добавлять.

Краткий ответ

Лечение Joomla после взлома состоит из пяти этапов: изолировать сайт и сохранить копию, закрыть уязвимый вход, найти и удалить вредоносный код в файлах и базе, заменить доступы и проверить работу сайта, затем включить постоянную защиту. Вредоносный код может остаться в шаблоне, модулях или настройках базы, поэтому одной проверки папки images недостаточно. Правила Nginx или Apache ниже блокируют запуск PHP в каталогах загрузок, но не заменяют обновление Joomla и расширений.

Что сделать в первые 30 минут

Первая задача, не удалить следы и не дать атакующему продолжить работу. Если есть признаки взлома: незнакомый администратор, редиректы, спам со страниц сайта, PHP-файлы в папке изображений, предупреждение поисковой системы или хостинга, временно ограничьте доступ к сайту технической заглушкой или правилами веб-сервера.

  1. Сохраните отдельную копию файлов сайта, дамп базы данных и журналы веб-сервера. Не перезаписывайте существующие резервные копии.
  2. Зафиксируйте время обнаружения, подозрительные URL, имена файлов и учётные записи. Эта информация поможет найти точку входа.
  3. Смените пароли администратора Joomla, панели хостинга, SSH или FTP, базы данных и почты. Удалите неизвестных пользователей с правами администратора.
  4. Закройте выполнение PHP в папках, куда можно загружать файлы. Это снижает риск повторного запуска веб-шелла ещё до полной очистки.

Не запускайте массовое удаление файлов по совпадению с одной строкой или датой. У Joomla и расширений бывают легитимные минифицированные и закодированные файлы. Сначала сделайте копию и проверьте каждый кандидат.

Шаг 1. Закройте вход, через который могли попасть на сайт

Обновление закрывает известную уязвимость, но не удаляет уже загруженный код. В панели Joomla откройте «Система → Обновление Joomla» и «Система → Управление → Расширения». Обновите ядро и используемые расширения до поддерживаемых версий. Неиспользуемые компоненты, плагины, шаблоны и языки лучше удалить через штатный менеджер расширений.

Сверяйте установленные версии с бюллетенями разработчика каждого расширения и с центром безопасности Joomla. Не ориентируйтесь на список уязвимостей из старой статьи или форума: номера CVE, затронутые версии и способы обхода меняются.

Что проверить Где искать Что сделать
Версия Joomla Панель администратора, «Система → Информация о системе» Обновить до поддерживаемой версии после резервной копии.
Расширения и шаблоны «Система → Управление → Расширения» Обновить используемые, удалить ненужные, отключить сомнительные до проверки.
Плагины com_ajax «Система → Плагины», фильтр по группе ajax Отключить то, что не используется. Для собственных обработчиков добавить проверку прав и CSRF-токена.
Учётные записи «Пользователи → Управление» Удалить неизвестные учётные записи и проверить группы доступа.

Шаг 2. Запретите запуск PHP в папках загрузок

Папки images, media, files, tmp, cache и logs предназначены для изображений, вложений, временных файлов и журналов. В нормальной Joomla PHP-код в них запускаться не должен. Если уязвимое расширение загрузит туда веб-шелл, правило ниже вернёт ошибку 403 вместо выполнения файла.

Nginx: куда вставить правило

Добавьте фрагмент в блок server конфигурации сайта, до общего обработчика PHP. В HestiaCP это обычно пользовательские файлы конфигурации домена nginx.conf_* и nginx.ssl.conf_*. Если сайт работает по HTTP и HTTPS, правило должно быть в обоих конфигурационных файлах. После изменения проверьте конфигурацию командой nginx -t и только затем перечитайте Nginx.

location ~* ^/(images|media|files|tmp|cache|logs|administrator/(logs|cache))/.+\.(php|phtml|phar|php[0-9]*)$ {
  deny all;
  return 403;
}

Если расширение хранит вложения в отдельной папке, добавьте её в список. Пример: images/baforms/uploads. Не запрещайте PHP в каталогах расширения целиком, пока не убедитесь, что там действительно не выполняется штатный код Joomla.

Apache: практическая настройка .htaccess в папках загрузок

Этот вариант подходит для Joomla на Apache, в том числе на хостингах Beget и Timeweb. Создайте отдельный файл .htaccess в каждой папке, куда сайт загружает или записывает файлы, но где PHP выполняться не должен: images, media, tmp, cache, logs, administrator/cache и administrator/logs.

Что именно нужно сделать: в каждой строке таблицы создайте файл с точным именем .htaccess (точка в начале имени обязательна) и вставьте в него один и тот же блок из следующего раздела. Не кладите правило в CSS-файл: CSS не может запретить выполнение PHP.

Папка на сервере Какой файл создать внутри папки Что вставить в файл
images/ images/.htaccess Блок для Apache 2.4 ниже.
media/ media/.htaccess Тот же блок для Apache 2.4.
tmp/ tmp/.htaccess Тот же блок для Apache 2.4.
cache/ cache/.htaccess Тот же блок для Apache 2.4.
logs/ logs/.htaccess Тот же блок для Apache 2.4.
administrator/cache/ administrator/cache/.htaccess Тот же блок для Apache 2.4.
administrator/logs/ administrator/logs/.htaccess Тот же блок для Apache 2.4.
images/baforms/uploads/ (при наличии) images/baforms/uploads/.htaccess Тот же блок для Apache 2.4, как дублирующий слой защиты.

Правило действует рекурсивно: файл в images защитит и images/baforms/uploads, и images/sppagebuilder. Для устойчивости полезно продублировать его непосредственно в папках загрузки расширений, например в images/baforms/uploads. Это поможет, если родительский .htaccess случайно заменят при восстановлении сайта или обновлении.

Содержимое .htaccess для Apache 2.4

Скопируйте этот блок без изменений в каждый из перечисленных файлов .htaccess. Это и есть полное содержимое каждого файла. Apache 2.4 используется на большинстве актуальных хостингов.

# Запрет выполнения любых серверных скриптов в этой папке
<FilesMatch "\.(php|php[0-9]*|phtml|pht|phtm|phar|phps|phpt|shtml|shtm|stm|cgi|fcgi|pl|py|sh|bash|asp|aspx|jsp|hphp|fla)$">
  Require all denied
</FilesMatch>
Options -Indexes

Такое правило вернёт 403 для файлов с расширениями .php, .phtml, .php5, .phar и других серверных скриптов из списка. Изображения, PDF и документы оно не блокирует, потому что они не совпадают с маской. Строка Options -Indexes дополнительно запрещает просмотр содержимого папки, если в ней нет индексного файла.

Не используйте php_flag engine off

На Beget, Timeweb и других конфигурациях с FastCGI или PHP-FPM директива php_flag engine off может вызвать ошибку 500. Для этой задачи достаточно Require all denied. Не добавляйте php_flag в .htaccess папок загрузки.

Если на хостинге Apache 2.2

Для старого Apache используйте прежний синтаксис доступа. Не смешивайте этот блок с вариантом для Apache 2.4 в одном и том же файле.

<FilesMatch "\.(php|php[0-9]*|phtml|pht|phar|phps|shtml|cgi|pl|py|sh|hphp|fla)$">
  Order allow,deny
  Deny from all
</FilesMatch>
Options -Indexes

Как проверить правило

Из корня сайта создайте временный PHP-файл, запросите его и затем сразу удалите. Вместо САЙТ подставьте свой домен. Первый запрос должен вернуть 403, а проверка изображения должна вернуть 200.

echo '<?php echo 42;' > images/__t.php
curl -I https://САЙТ/images/__t.php
curl -I https://САЙТ/images/logo.png
rm images/__t.php

.htaccess читает только Apache. На Nginx, в том числе на сервере INSIB, этот файл игнорируется, поэтому ограничение настраивают в конфигурации Nginx, как показано выше. Это защитный слой, а не лечение: правило не даст загруженному веб-шеллу запуститься, но уязвимость в расширении (например, Balbooa, SP Page Builder или JCE) закрывают обновлением или патчем. Нужны оба действия.

Защита папок загрузки Joomla от запуска PHP-файлов
Веб-сервер должен блокировать запуск исполняемых файлов в каталогах, предназначенных для загрузок.

Шаг 3. Найдите подозрительные файлы без удаления

Подключитесь к серверу по SSH и начните с файлов, которые появились незадолго до инцидента, а также с PHP в каталогах, предназначенных для загрузок. Выполняйте команды из корня Joomla, где лежат configuration.php и папки administrator, images, plugins.

find . -type f -name "*.php" -mtime -14 -print
find images media files tmp cache logs -type f -name "*.php" -print
grep -RInE "base64_decode|gzinflate|eval[[:space:]]*\(|shell_exec|assert[[:space:]]*\(" .

Эти команды не доказывают заражение, а формируют список для проверки. Сначала сравните подозрительный файл с дистрибутивом Joomla или исходниками расширения. Затем перенесите его в карантин за пределы публичной папки либо переименуйте с расширением .disabled, если уверены, что файл вредоносный. Не удаляйте оригинал до завершения расследования.

Какие каталоги проверять в первую очередь

  • images, media, files, tmp, cache: PHP, файлы с двойным расширением и неизвестные .htaccess.
  • templates и plugins: новые или изменённые PHP-файлы, вставки JavaScript с обфускацией, незнакомые include и require.
  • Корень сайта: index.php, .htaccess, configuration.php и файлы с похожими именами, например configuration.php.bak.
  • administrator: новые файлы и неизвестные расширения, особенно если они появились одновременно с инцидентом.

Не пропустите файлы без расширения и шаблоны-двойники

Закладка не обязана иметь расширение .php. Проверьте файлы без расширения в каталогах ядра и расширений: если такой файл содержит PHP-тег, он требует отдельной проверки. Также просмотрите новые папки в templates: шаблон с двумя-тремя файлами, случайным именем и неизвестной записью в менеджере расширений может быть маскировкой. Не удаляйте небольшой дочерний шаблон автоматически, сначала сравните его с установленным и проверьте дату создания.

find libraries includes components plugins modules -type f ! -name "*.*" -exec grep -l '<?php' {} \;
find templates -mindepth 1 -maxdepth 1 -type d -print
find templates -type f -name "templateDetails.xml" -print

В каталогах, куда загружаются файлы, ищите оба PHP-тега: <?php и <?=. Проверка только первого пропускает короткий вывод PHP. Для всего каталога images результат нужно проверять вручную, так как строка может случайно встретиться в бинарном файле. Для узких папок загрузки расширений совпадение значительно подозрительнее.

grep -ralE '<\?php|<\?=' images/baforms/uploads/ media/ tmp/
grep -rlE 'x-httpd|SetHandler.*php|ForceType.*php' --include='.htaccess' .

Незнакомый .htaccess может включать обработку PHP для нестандартного расширения. При этом не удаляйте правила, где встречаются только MIME-типы шрифтов, SVG, WebP или AVIF, они часто легитимны.

Шаг 4. Проверьте базу данных, а не только файлы

После взлома вредоносный JavaScript нередко живёт в настройках шаблона, параметрах модулей или тексте материалов. Он возвращается на сайт даже после замены файлов, поэтому базу нужно просматривать отдельно. Перед любым редактированием выгрузите SQL-дамп.

В phpMyAdmin или другом клиенте базы по очереди проверьте таблицы с вашим префиксом: template_styles, modules, content, extensions. Ищите конструкции fromCharCode, eval(, base64_decode, _0x, неожиданные внешние домены и скрытые iframe. Префикс таблиц у Joomla может быть не jos_, поэтому замените его на фактический.

SELECT id, template, params
FROM prefix_template_styles
WHERE params LIKE '%fromCharCode%'
   OR params LIKE '%eval(%'
   OR params LIKE '%_0x%';

SQL-запрос выше только ищет записи, ничего не удаляет. Перед очисткой подозрительной строки сравните её с резервной копией, датой изменения и кодом шаблона. Если неясно, какая часть параметров штатная, передайте специалисту экспорт конкретной записи, а не весь дамп с персональными данными.

Проверьте администраторов Joomla

Удалённый доступ может сохраниться в базе через учётную запись Super User. В панели Joomla откройте «Пользователи → Управление», сверяйте каждого администратора с владельцем сайта и фиксируйте сомнительные записи до удаления. Признаки риска: незнакомое имя, технический почтовый домен, дата регистрации рядом с инцидентом или пустая дата последнего входа. После проверки удалите лишние учётные записи и смените пароли оставшимся.

SELECT u.id, u.username, u.email, u.registerDate, u.lastvisitDate
FROM prefix_users u
JOIN prefix_user_usergroup_map m ON m.user_id = u.id
WHERE m.group_id IN (7, 8);

Замените prefix_ на фактический префикс таблиц. Запрос только выводит список и ничего не меняет.

Проверка базы данных Joomla после взлома сайта
После инцидента проверяют не только файлы сайта, но и настройки шаблона, модули и записи базы данных.

Шаг 5. Безопасно восстановите ядро Joomla и расширения

Когда точка входа закрыта и список подозрительных файлов составлен, замените ядро Joomla на чистый дистрибутив той же, а затем актуальной поддерживаемой версии. Это безопаснее, чем пытаться вручную восстановить каждый системный файл. Не перезаписывайте без проверки configuration.php, папку images и доработки шаблона: там могут находиться рабочие настройки и пользовательские данные.

  1. Сделайте контрольный дамп базы и копию файлов после изоляции.
  2. Обновите Joomla штатным способом из панели администратора или по инструкции хостинга.
  3. Переустановите используемые расширения из официальных архивов разработчиков.
  4. Проверьте журнал ошибок, форму обратной связи, авторизацию, отправку писем, поиск и основные посадочные страницы.
  5. Повторно выполните поиск подозрительных файлов и строк в базе.

Сравните ядро с точной версией Joomla

Если заражение могло изменить один системный файл, одной проверки по датам недостаточно. Скачайте полный пакет ровно той версии Joomla, которая установлена на сайте, распакуйте его вне публичной папки и сравните каталоги ядра. Не сравнивайте сайт с соседним проектом: отличия версий дадут большой объём ложных срабатываний.

unzip -q Joomla_X.Y.Z-Stable-Full_Package.zip -d /tmp/joomla-stock
diff -rq /tmp/joomla-stock/libraries ./libraries
diff -rq /tmp/joomla-stock/includes ./includes

Сначала сохраните различающиеся файлы в карантин или отдельный архив, затем восстановите их из чистого дистрибутива. Если SSH недоступен, в администраторской части Joomla используйте «Система → Обновление Joomla → Переустановить файлы ядра». Эта операция обновляет ядро, но не заменяет проверку расширений, шаблона и базы.

Проверьте клоакинг и журналы веб-сервера

Часть заражений показывает спам или редирект только поисковому боту либо мобильному посетителю с переходом из поиска. Обычная проверка сайта в браузере не гарантирует, что страницы чистые. Сравните размер ответа и конечный URL для нескольких User-Agent, затем повторите проверку с внешнего подключения, которое не добавлено в доверенные IP.

curl -s -A "Mozilla/5.0" https://site.ru/ | wc -c
curl -s -A "Googlebot/2.1" https://site.ru/ | wc -c
curl -s -A "YandexBot/3.0" https://site.ru/ | wc -c
curl -s -o /dev/null -w "%{url_effective}\n" -L -A "Googlebot/2.1" https://site.ru/

Сравнивайте не одно число, а несколько страниц и профилей. Существенное необъяснимое расхождение, чужой конечный домен, скрытый iframe или неизвестный JavaScript требуют расследования. В журналах ищите предупреждения PHP, обращения к неожиданным файлам, ошибки include и подозрительные запросы к загрузочным endpoint.

grep -aE 'PHP Warning|Fatal error|include\(' /var/log/nginx/domains/site.log
grep -aE 'upload|com_ajax|profiles\.import' /var/log/nginx/domains/site.log

Путь к журналу зависит от хостинга. Не публикуйте фрагменты логов с персональными данными, токенами, cookie или паролями.

Шаг 6. Защитите собственный com_ajax-обработчик

Обработчик com_ajax не получает ограничения доступа автоматически только потому, что метод находится в административном расширении. Если вы поддерживаете собственный ajax-плагин, проверка должна находиться в самом начале публичного метода обработчика, до любой работы с входными данными или файлами.

Откройте PHP-файл метода onAjax... вашего плагина, обычно он находится в папке plugins/ajax/имя_плагина или в его классе расширения. Вставьте проверку сразу после открытия метода. Замените com_example на имя своего компонента и адаптируйте код под версию Joomla и архитектуру плагина.

<?php
public function onAjaxMyplugin()
{
  $user = \Joomla\CMS\Factory::getUser();
  if ($user->guest || !$user->authorise('core.manage', 'com_example')) {
    throw new \RuntimeException('Access forbidden', 403);
  }
  \Joomla\CMS\Session\Session::checkToken('request') or throw new \RuntimeException('Invalid token', 403);
  // Основная логика обработчика
}

Проверка токена подходит для запросов из административного интерфейса, где токен передаётся штатно. Для публичной формы авторизация может быть другой, но проверка типа файла, размера, MIME-типа и права на загрузку всё равно обязательна.

Шаг 7. Смените доступы и настройте регулярную защиту

После очистки считайте скомпрометированными все секреты, которые были доступны на сервере. Смена одного пароля администратора не закрывает доступ через FTP, базу данных или API-токен.

  • Смените пароли Joomla, хостинга, SSH или FTP, базы данных, почтовых ящиков и внешних сервисов.
  • Измените секретный ключ Joomla после проверки совместимости с интеграциями, которые могут его использовать.
  • Включите двухфакторную аутентификацию для администраторов и удалите ненужные учётные записи.
  • Отключите самостоятельную регистрацию, если она не нужна проекту.
  • Настройте внешние резервные копии и периодически проверяйте, что из них можно восстановить чистый сайт.
  • Подключите WAF или защитное расширение как дополнительный слой, а не как замену обновлениям.

После лечения настройте три постоянные проверки

Повторная проверка должна быть регулярной, иначе проблему замечают только после жалобы из поиска или блокировки хостингом. Достаточно следить за изменением ответа главной страницы, клоакингом и индикаторами компрометации в публичном HTML.

  1. Контроль доступности и размера страницы. Сохраняйте медиану размера ответа за последние проверки. Резкое необъяснимое уменьшение или рост требует проверки шаблона и внешних вставок.
  2. Клоакинг-тест. По расписанию запрашивайте ключевые страницы как обычный посетитель, Googlebot, YandexBot и мобильный браузер, а также проверяйте конечный URL после редиректов.
  3. Контроль изменений. Получайте уведомление о новых PHP-файлах в папках загрузки, незнакомых администраторах и изменениях важных системных файлов.

Сначала исключите штатные обновления Joomla и публикации контента из сигналов мониторинга. Цель мониторинга не в большом количестве тревог, а в том, чтобы быстро увидеть действительно необычное изменение.

Комментарий специалиста INSIB

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

Нужна помощь с лечением сайта на Joomla

Проведём диагностику, найдём точку входа, очистим файлы и базу, настроим защиту и проверим восстановление сайта.

Обсудить задачу

Частые вопросы

Можно ли просто восстановить сайт из резервной копии?

Можно только после проверки даты и чистоты копии. Если резервная копия сделана после взлома или уже содержит вредоносный код, восстановление вернёт проблему.

Достаточно ли обновить Joomla и расширения?

Нет. Обновление закрывает известную уязвимость, но не удаляет веб-шелл, скрипт в шаблоне или изменённую запись базы данных.

Почему PHP в папке images опасен?

Папка изображений не должна содержать исполняемый PHP-код. Если веб-сервер запускает такой файл, атакующий получает возможность выполнять команды от имени сайта.

Нужно ли менять пароль базы данных?

Да, если есть вероятность доступа атакующего к configuration.php, резервным копиям или панели хостинга. После смены не забудьте обновить параметры подключения в configuration.php.

Что делать, если я не уверен в подозрительном файле?

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

Поможет ли WAF?

WAF блокирует часть известных атак и полезен как дополнительный барьер. Он не заменяет обновления, ограничение выполнения PHP и проверку уже заражённого сайта.

Что важно запомнить

При взломе Joomla действуйте последовательно: сохраните доказательства и копию, перекройте повторный вход, проверьте файлы и базу, восстановите компоненты из чистых источников, смените все секреты и запретите PHP в каталогах загрузок. Если нет доступа к серверу или непонятно, что именно изменено, безопаснее передать диагностику специалисту, чем удалять файлы наугад.

Полезные статьи