MODX Revolution заслуженно считается одной из самых безопасных CMS. За 18 лет работы с этой системой я сталкивался с различными угрозами — от примитивных попыток взлома до серьёзных DDoS-атак. В этой статье поделюсь реальным опытом защиты сайтов и расскажу, как обеспечить максимальную безопасность вашего MODX-проекта.
Почему MODX безопаснее конкурентов
Архитектурные преимущества
MODX изначально проектировался с учётом безопасности. В отличие от WordPress с его «макаронным» кодом, где PHP, JavaScript и HTML переплетаются в один клубок, MODX имеет чёткую архитектуру разделения логики и представления.
Ключевые особенности:
- Система разрешений на уровне ресурсов и элементов
- Отсутствие прямого доступа к файлам системы через URL
- Контролируемое выполнение PHP-кода только в специально отведённых местах
- Защищённые директории с правильными настройками .htaccess
Реальный опыт: как MODX отражал атаки
За годы работы наблюдал множество попыток взлома сайтов клиентов. Вот несколько показательных случаев:
DDoS-атака на интернет-магазин Сайт на miniShop2 подвергся массированной DDoS-атаке — тысячи запросов в секунду к формам заказа. MODX справился без дополнительной защиты благодаря:
- Эффективному кешированию запросов
- Встроенной защите от переполнения форм
- Правильной настройке лимитов PHP
SQL-инъекции через поисковые формы Злоумышленники пытались внедрить вредоносный код через mSearch2. Попытки провалились из-за:
- Автоматической экранизации входных данных в xPDO
- Использования подготовленных запросов
- Валидации на уровне процессоров
Базовая настройка безопасности
Перемещение системных папок
Первое, что нужно сделать после установки — переместить критически важные папки за пределы веб-корня.
# В .htaccess корневой директории
RewriteEngine On
RewriteRule ^core/ - [F,L]
RewriteRule ^manager/ manager/index.php [L]
Рекомендуемая структура:
/home/user/
├── public_html/
│ ├── assets/
│ ├── connectors/
│ └── index.php
├── modx_core/ # Перемещена из public_html/core/
└── manager/ # Защищена дополнительно
Настройка config.core.php
<?php
define('MODX_CORE_PATH', '/home/user/modx_core/');
define('MODX_CONFIG_KEY', 'config');
Защита административной панели
1. Изменение URL менеджера
// В config/core.php
$modx_manager_path = '/secret_admin_path/';
2. HTTP Basic Auth для менеджера
# В manager/.htaccess
AuthType Basic
AuthName "Admin Area"
AuthUserFile /path/to/.htpasswd
Require valid-user
3. Ограничение по IP
<RequireAll>
Require ip 192.168.1.100
Require ip 203.0.113.0/24
</RequireAll>
Система разрешений и пользователи
Принцип минимальных привилегий
// Создание роли контент-менеджера
$policy = $modx->newObject('modAccessPolicy');
$policy->set('name', 'ContentManager');
$policy->set('description', 'Управление контентом без системных настроек');
$policy->set('data', json_encode([
'resource_list' => true,
'resource_edit' => true,
'resource_create' => true,
'element_tv_edit' => true,
// Запрещены системные операции
'settings' => false,
'packages' => false,
'sources' => false
]));
Настройка контекстов безопасности
// Отдельный контекст для админки
$adminContext = $modx->newObject('modContext');
$adminContext->set('key', 'admin');
$adminContext->set('description', 'Административный контекст');
// Настройки контекста
$settings = [
'site_url' => 'https://admin.example.com/',
'base_url' => '/',
'error_page' => 1,
'unauthorized_page' => 2
];
Защита от популярных угроз
SQL-инъекции
MODX использует xPDO ORM, который автоматически экранирует данные:
// ПРАВИЛЬНО - безопасное получение данных
$userId = (int) $_GET['user_id'];
$user = $modx->getObject('modUser', $userId);
// ЕЩЁ ЛУЧШЕ - с дополнительной проверкой
$userId = $modx->getOption('user_id', $_GET, 0, 'is_int');
if ($userId > 0) {
$user = $modx->getObject('modUser', $userId);
}
// НЕПРАВИЛЬНО - уязвимый код
$query = "SELECT * FROM users WHERE id = " . $_GET['user_id'];
XSS-атаки
// В сниппетах всегда экранируем вывод
$output = htmlspecialchars($input, ENT_QUOTES, 'UTF-8');
// Для пользовательского контента
$cleanContent = $modx->sanitizeString($userContent);
// В шаблонах используем фильтры
[[*content:htmlent]]
[[+userInput:strip_tags]]
CSRF-защита
// В формах добавляем токен
$token = $modx->user->getUserToken($modx->context->get('key'));
echo '<input type="hidden" name="csrf_token" value="' . $token . '">';
// Проверка в процессоре
if (!$modx->user->validateUserToken($scriptProperties['csrf_token'], $modx->context->get('key'))) {
return $modx->error->failure('Ошибка безопасности');
}
Обновления и мониторинг
Стратегия обновлений
1. Тестовое окружение
# Создание копии продакшена
rsync -av --exclude-from=exclude.txt production/ staging/
mysqldump production_db | mysql staging_db
2. Поэтапное обновление
- Сначала дополнения и компоненты
- Затем ядро MODX
- Проверка совместимости после каждого этапа
3. План отката
// Скрипт быстрого отката
$backup_date = '2026-02-28_14-30';
exec("mysql database < backups/db_$backup_date.sql");
exec("rsync -av backups/files_$backup_date/ ./");
Автоматизированный мониторинг
// Сниппет проверки целостности системы
class SecurityMonitor {
public function checkCoreFiles() {
$coreFiles = [
MODX_CORE_PATH . 'config/config.inc.php',
MODX_CORE_PATH . 'model/modx/modx.class.php'
];
foreach ($coreFiles as $file) {
if (!file_exists($file)) {
$this->alert('Отсутствует критический файл: ' . $file);
}
$hash = md5_file($file);
if ($hash !== $this->getExpectedHash($file)) {
$this->alert('Изменён системный файл: ' . $file);
}
}
}
public function checkLoginAttempts() {
$threshold = 10; // максимум попыток за час
$attempts = $modx->getCount('modUserLog', [
'action' => 'login_failed',
'occurred:>' => strtotime('-1 hour')
]);
if ($attempts > $threshold) {
$this->lockdown();
}
}
}
Резервное копирование
Автоматизированная система бэкапов
#!/bin/bash
# backup_modx.sh
DATE=$(date +"%Y-%m-%d_%H-%M")
BACKUP_DIR="/backups/$DATE"
SITE_DIR="/home/user/public_html"
DB_NAME="modx_database"
# Создание директории
mkdir -p $BACKUP_DIR
# Бэкап базы данных
mysqldump --single-transaction --routines --triggers $DB_NAME > $BACKUP_DIR/database.sql
# Бэкап файлов (исключая кеш и временные файлы)
rsync -av --exclude='core/cache/' --exclude='core/logs/' $SITE_DIR/ $BACKUP_DIR/files/
# Проверка целостности
if [ -s $BACKUP_DIR/database.sql ] && [ -d $BACKUP_DIR/files ]; then
echo "Бэкап создан успешно: $BACKUP_DIR"
# Удаление старых бэкапов (старше 30 дней)
find /backups -type d -mtime +30 -exec rm -rf {} \;
else
echo "ОШИБКА: Бэкап не создан!"
exit 1
fi
Настройка cron для автобэкапов
# Ежедневный бэкап в 3:00
0 3 * * * /path/to/backup_modx.sh
# Еженедельный полный бэкап в воскресенье в 2:00
0 2 * * 0 /path/to/full_backup_modx.sh
Лучшие практики безопасности
Чек-лист базовой защиты
Файловая система:
- Системные папки перенесены из веб-корня
- Права доступа настроены корректно (755 для папок, 644 для файлов)
- .htaccess файлы защищают критичные директории
База данных:
- Используется отдельный пользователь с минимальными правами
- Префикс таблиц изменён с стандартного
- Настроено шифрование соединений
Учётные записи:
- Администраторский аккаунт переименован
- Используются сложные пароли
- Включена двухфакторная аутентификация
Конфигурация хостинга
При выборе хостинга обращайте внимание на:
PHP настройки:
- disable_functions должна включать опасные функции
- open_basedir ограничивает доступ к файловой системе
- Актуальная версия PHP с последними патчами безопасности
Рекомендую Timeweb — у них хорошо настроенная безопасность для MODX и круглосуточная техподдержка.
Реагирование на инциденты
План действий при взломе
1. Немедленные действия:
# Блокировка сайта
echo "Сайт временно недоступен" > index.html
# Создание слепка для анализа
cp -r /site /forensic_copy_$(date +%Y%m%d_%H%M)
# Смена паролей
mysql -u root -p -e "UPDATE modx_users SET password = MD5('new_temp_password') WHERE username = 'admin'"
2. Анализ и восстановление:
- Изучение логов доступа и ошибок
- Поиск изменённых файлов
- Проверка целостности базы данных
- Восстановление из проверенной резервной копии
Превентивные меры
// Мониторинг изменений файлов
class FileIntegrityChecker {
private $hashFile = 'core/cache/file_hashes.json';
public function updateHashes() {
$files = $this->getCriticalFiles();
$hashes = [];
foreach ($files as $file) {
$hashes[$file] = md5_file($file);
}
file_put_contents($this->hashFile, json_encode($hashes));
}
public function checkIntegrity() {
$storedHashes = json_decode(file_get_contents($this->hashFile), true);
$changes = [];
foreach ($storedHashes as $file => $hash) {
if (!file_exists($file) || md5_file($file) !== $hash) {
$changes[] = $file;
}
}
if (!empty($changes)) {
$this->notifyAdmin($changes);
}
}
}
Заключение
Безопасность MODX — это не одноразовая настройка, а постоянный процесс. Система даёт отличные инструменты защиты из коробки, но их нужно правильно использовать.
Основные принципы:
- Минимизация атаки поверхности — скрывайте всё, что можно скрыть
- Глубокая защита — используйте несколько уровней безопасности
- Регулярное обслуживание — обновления, мониторинг, бэкапы
- Подготовка к худшему — план восстановления должен быть отработан заранее
MODX позволяет создавать действительно безопасные сайты без лишних сложностей. В отличие от других CMS, здесь не нужно устанавливать десятки плагинов безопасности — большинство защит работает на уровне ядра.
Связанные статьи: SEO-продвижение сайтов на MODX