Большинство статей по безопасности Joomla повторяют одни и те же рекомендации: обновляйтесь, используйте сложные пароли, ставьте Admin Tools. Это работает, но есть и другой путь — защита на уровне файловой системы и веб-сервера, которая не зависит от уязвимостей в коде.

В этой статье я поделюсь методами, которые применил на реальном проекте (интернет-магазин на Joomla + VirtueMart) и которые кардинально отличаются от стандартных подходов.


Основная идея: запретить, а не лечить

Традиционный подход к безопасности Joomla строится на обнаружении и блокировке атак через плагины (Admin Tools, RSFirewall и т.д.). Мой подход — превентивный: даже если злоумышленник найдет уязвимость и загрузит вредоносный файл, он не сможет его выполнить.

Это достигается через два ключевых механизма:

  1. Запрет выполнения PHP на уровне веб-сервера (Nginx) в папках, где его быть не должно
  2. Защита файлов от изменения на уровне файловой системы (chattr +i)

1. Запрет выполнения PHP через Nginx

Стандартный подход (неэффективный)

Обычно в Joomla используют .htaccess с правилами вроде:

<FilesMatch "\.(php|phtml)$">
    Order allow,deny
    Deny from all
</FilesMatch>

Но это работает только в Apache и не защищает от обхода через другие расширения.

Мой подход (Nginx)

В конфигурации Nginx я добавил следующие блоки:

1.1. Защита папок загрузок и кэша

# ЗАПРЕТ PHP В ПАПКАХ ЗАГРУЗОК
location ~* ^/(images|media|stories)/.*\.(php|phtml|php\d*|phar)$ {
    deny all;
    return 403;
}

# ЗАПРЕТ PHP В ПАПКАХ КЭША И ВРЕМЕННЫХ
location ~* ^/(tmp|cache|administrator/cache|images/tmp)/.*\.(php|phtml|php\d*|phar)$ {
    deny all;
    return 403;
}

Почему это работает:

  • Перехватывает любой запрос к PHP-файлам внутри этих папок
  • Возвращает 403 Forbidden, даже если файл физически существует
  • Не зависит от Joomla или PHP

1.2. Защита конфигурационного файла

# ЗАПРЕТ ДОСТУПА К CONFIGURATION.PHP
location ~ ^/configuration\.php$ {
    deny all;
    return 403;
}

1.3. Защита специфических папок сторонних компонентов

# ЗАПРЕТ PHP В ПАПКЕ com_excel2vm/xls
location /administrator/components/com_excel2vm/xls/ {
    location ~ \.(php|phtml|php\d*|phar)$ {
        deny all;
        return 403;
    }
}

1.4. Запрет листинга директорий

location / {
    autoindex off;
    try_files /does_not_exists @fallback;
}

2. Защита файлов через chattr +i (неизменяемость)

Этот метод я считаю самым мощным, но о нем почти не пишут в контексте Joomla.

Что такое chattr +i?

Команда chattr +i делает файл неизменяемым. Даже root не сможет его изменить, переименовать или удалить, пока атрибут не будет снят.

# Защита файлов от изменения
chattr +i /var/www/www-root/data/www/mi55.ru/index.php
chattr +i /var/www/www-root/data/www/mi55.ru/configuration.php
chattr +i /var/www/www-root/data/www/mi55.ru/defines.php

Что я защитил рекурсивно

# Защита всех компонентов, модулей, плагинов
chattr -R +i /var/www/www-root/data/www/mi55.ru/components/
chattr -R +i /var/www/www-root/data/www/mi55.ru/administrator/components/
chattr -R +i /var/www/www-root/data/www/mi55.ru/modules/
chattr -R +i /var/www/www-root/data/www/mi55.ru/plugins/
chattr -R +i /var/www/www-root/data/www/mi55.ru/templates/
chattr -R +i /var/www/www-root/data/www/mi55.ru/libraries/
chattr -R +i /var/www/www-root/data/www/mi55.ru/api/
chattr -R +i /var/www/www-root/data/www/mi55.ru/cli/

Почему это эффективно

  1. Даже если злоумышленник получит доступ к файловой системе (например, через LFI), он не сможет изменить код
  2. Защита сохраняется после обновлений (нужно только временно снять атрибут)
  3. Работает на уровне ядра Linux — обойти сложнее, чем права доступа (chmod)

Проверка защиты

# Просмотр защищенных файлов
lsattr /var/www/www-root/data/www/mi55.ru/*.php | grep "i-"

# Результат:
----i---------e------- /var/www/.../configuration.php
----i---------e------- /var/www/.../defines.php
----i---------e------- /var/www/.../index.php

3. Регулярная очистка мусора

Не менее важный аспект — удаление лишних файлов, которые могут стать вектором атаки.

Что я удалил:

  1. Файлы macOS (._*, .DS_Store, __MACOSX) — они не нужны для работы
  2. Бэкапы в корне (папка /1C_DB_Backup/ была удалена)
  3. Пустые или подозрительные файлы (например, components/com_excel2vm/excel2vm.php размером 0 байт)
# Скрипт очистки
find /var/www/www-root/data/www/mi55.ru -name "._*" -type f -delete
find /var/www/www-root/data/www/mi55.ru -name ".DS_Store" -type f -delete
find /var/www/www-root/data/www/mi55.ru -name "__MACOSX" -type d -exec rm -rf {} \;

Сравнение с традиционными методами

Аспект Традиционный подход Мой подход
Защита от выполнения PHP Плагины (Admin Tools) Nginx (серверный уровень)
Защита файлов Права доступа (chmod) Неизменяемость (chattr +i)
Защита конфигурации .htaccess Запрет в Nginx + chattr
Зависимость от Joomla Высокая Минимальная
Обход через уязвимости Возможен Затруднен
Сложность настройки Низкая Средняя
Надежность Средняя Высокая

Важные нюансы

1. Обновление компонентов

При обновлении Joomla или VirtueMart необходимо временно снять защиту:

# Снятие защиты перед обновлением
chattr -i /var/www/www-root/data/www/mi55.ru/index.php
chattr -R -i /var/www/www-root/data/www/mi55.ru/libraries/

# ... выполнить обновление ...

# Повторное применение защиты
chattr +i /var/www/www-root/data/www/mi55.ru/index.php
chattr -R +i /var/www/www-root/data/www/mi55.ru/libraries/

2. Папки, которые нельзя защищать

Некоторые папки должны оставаться доступными для записи:

# НЕ ЗАЩИЩАТЬ!
/tmp/
/cache/
/administrator/cache/
/images/
/media/
/stories/
/logs/
/t3-assets/

Мониторинг и поддержка

Для поддержания безопасности я использую простой скрипт:

#!/bin/bash
# /usr/local/bin/security-check.sh

SITE="/var/www/www-root/data/www/mi55.ru"

echo "=== ПРОВЕРКА НОВЫХ PHP-ФАЙЛОВ ==="
find $SITE -name "*.php" -mtime -1 -not -path "*/tmp/*" -not -path "*/cache/*" 2>/dev/null

echo "=== ПРОВЕРКА ЗАЩИЩЕННЫХ ФАЙЛОВ ==="
lsattr $SITE/*.php 2>/dev/null | grep "i-"

echo "=== ПРОВЕРКА ПРАВ ДОСТУПА ==="
find $SITE -type f -perm /111 -name "*.php" 2>/dev/null | head -10

Результаты

После применения этих методов:

  1. Все проверки безопасности пройдены — curl-запросы к защищенным папкам возвращают 403
  2. Сайт работает стабильно — никаких проблем с производительностью
  3. Нет ложных срабатываний — легитимные запросы проходят нормально
  4. Упрощен мониторинг — теперь я проверяю только новые файлы, а не их содержимое

Заключение

Традиционные методы защиты Joomla хороши, но они не дают полной гарантии. Добавление серверного уровня защиты (Nginx) и неизменяемости файлов (chattr +i) создает многоуровневую систему, которую сложно обойти даже при наличии уязвимости в коде.

Этот подход требует больше времени на первоначальную настройку, но окупается за счет:

  • Минимальной зависимости от Joomla-плагинов
  • Защиты даже в случае компрометации файловой системы
  • Простоты мониторинга и обслуживания

Помните: безопасность — это процесс, а не состояние. Регулярно проверяйте новые файлы, обновляйте компоненты и адаптируйте защиту под меняющиеся угрозы.