Лучшие практики безопасности
2.5.x ✅ 4.0.x ✅
Этот документ предоставляет комплексные рекомендации по безопасности для разработчиков модулей XOOPS. Следование этим рекомендациям поможет гарантировать, что ваши модули безопасны и не введут уязвимостей в установки XOOPS.
Принципы безопасности
Заголовок раздела «Принципы безопасности»Каждый разработчик XOOPS должен следовать этим фундаментальным принципам безопасности:
- Защита в глубину: Реализуйте несколько слоев управления безопасностью
- Принцип минимального привилегия: Предоставляйте только минимально необходимые права доступа
- Валидация входных данных: Никогда не доверяйте пользовательскому вводу
- Безопасность по умолчанию: Безопасность должна быть конфигурацией по умолчанию
- Простота: Сложные системы сложнее защищать
Связанная документация
Заголовок раздела «Связанная документация»- CSRF-Protection - Система токенов и класс XoopsSecurity
- Input-Sanitization - MyTextSanitizer и валидация
- SQL-Injection-Prevention - Практики безопасности базы данных
Контрольный список быстрой справки
Заголовок раздела «Контрольный список быстрой справки»Перед выпуском вашего модуля убедитесь:
- Все формы включают токены XOOPS
- Все пользовательские входные данные валидируются и очищаются
- Все выходные данные должным образом экранируются
- Все запросы к базе данных используют параметризованные выражения
- Загрузки файлов должным образом валидируются
- Проверки аутентификации и авторизации на месте
- Обработка ошибок не раскрывает конфиденциальную информацию
- Конфиденциальная конфигурация защищена
- Библиотеки третьих сторон актуальны
- Проведено тестирование безопасности
Аутентификация и авторизация
Заголовок раздела «Аутентификация и авторизация»Проверка аутентификации пользователя
Заголовок раздела «Проверка аутентификации пользователя»// Проверка, вошёл ли пользовательif (!is_object($GLOBALS['xoopsUser'])) { redirect_header(XOOPS_URL, 3, _NOPERM); exit();}Проверка прав доступа пользователя
Заголовок раздела «Проверка прав доступа пользователя»// Проверка, имеет ли пользователь право доступа к этому модулюif (!$GLOBALS['xoopsUser']->isAdmin($xoopsModule->mid())) { redirect_header(XOOPS_URL, 3, _NOPERM); exit();}
// Проверка определённого разрешения$moduleHandler = xoops_getHandler('module');$module = $moduleHandler->getByDirname('mymodule');$moduleperm_handler = xoops_getHandler('groupperm');$groups = $GLOBALS['xoopsUser']->getGroups();
if (!$moduleperm_handler->checkRight('mymodule_view', $item_id, $groups, $module->getVar('mid'))) { redirect_header(XOOPS_URL, 3, _NOPERM); exit();}Настройка разрешений модуля
Заголовок раздела «Настройка разрешений модуля»// Создание разрешения в функции установки/обновления$gpermHandler = xoops_getHandler('groupperm');$gpermHandler->deleteByModule($module->getVar('mid'), 'mymodule_view');
// Добавление разрешения для всех групп$groups = [XOOPS_GROUP_ADMIN, XOOPS_GROUP_USERS, XOOPS_GROUP_ANONYMOUS];foreach ($groups as $group_id) { $gpermHandler->addRight('mymodule_view', 1, $group_id, $module->getVar('mid'));}Безопасность сеанса
Заголовок раздела «Безопасность сеанса»Лучшие практики обработки сеанса
Заголовок раздела «Лучшие практики обработки сеанса»- Не сохраняйте конфиденциальную информацию в сеансе
- Регенерируйте ID сеанса после входа/изменения привилегий
- Валидируйте данные сеанса перед использованием
// Регенерация ID сеанса после входаsession_regenerate_id(true);
// Валидация данных сеансаif (isset($_SESSION['mymodule_user_id'])) { $user_id = (int)$_SESSION['mymodule_user_id']; // Проверка наличия пользователя в базе данных}Предотвращение фиксации сеанса
Заголовок раздела «Предотвращение фиксации сеанса»// После успешного входаsession_regenerate_id(true);$_SESSION['mymodule_user_ip'] = $_SERVER['REMOTE_ADDR'];
// При последующих запросахif ($_SESSION['mymodule_user_ip'] !== $_SERVER['REMOTE_ADDR']) { // Возможная попытка перехвата сеанса session_destroy(); redirect_header('index.php', 3, 'Session error'); exit();}Безопасность загрузки файлов
Заголовок раздела «Безопасность загрузки файлов»Валидация загрузки файлов
Заголовок раздела «Валидация загрузки файлов»// Проверка корректной загрузки файлаif (!isset($_FILES['userfile']) || $_FILES['userfile']['error'] != UPLOAD_ERR_OK) { redirect_header('index.php', 3, 'File upload error'); exit();}
// Проверка размера файлаif ($_FILES['userfile']['size'] > 1000000) { // Лимит 1MB redirect_header('index.php', 3, 'File too large'); exit();}
// Проверка типа файла$allowed_types = ['image/jpeg', 'image/png', 'image/gif'];if (!in_array($_FILES['userfile']['type'], $allowed_types)) { redirect_header('index.php', 3, 'Invalid file type'); exit();}
// Валидация расширения файла$filename = $_FILES['userfile']['name'];$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));$allowed_extensions = ['jpg', 'jpeg', 'png', 'gif'];if (!in_array($ext, $allowed_extensions)) { redirect_header('index.php', 3, 'Invalid file extension'); exit();}Использование загрузчика XOOPS
Заголовок раздела «Использование загрузчика XOOPS»include_once XOOPS_ROOT_PATH . '/class/uploader.php';
$allowed_mimetypes = ['image/gif', 'image/jpeg', 'image/png'];$maxsize = 1000000; // 1MB$maxwidth = 1024;$maxheight = 768;$upload_dir = XOOPS_ROOT_PATH . '/uploads/mymodule';
$uploader = new XoopsMediaUploader( $upload_dir, $allowed_mimetypes, $maxsize, $maxwidth, $maxheight);
if ($uploader->fetchMedia('userfile')) { $uploader->setPrefix('mymodule_');
if ($uploader->upload()) { $filename = $uploader->getSavedFileName(); // Сохранение имени файла в базе данных } else { echo $uploader->getErrors(); }} else { echo $uploader->getErrors();}Безопасное сохранение загруженных файлов
Заголовок раздела «Безопасное сохранение загруженных файлов»// Определение каталога загрузки вне веб-корня$upload_dir = XOOPS_VAR_PATH . '/uploads/mymodule';
// Создание каталога, если его не существуетif (!is_dir($upload_dir)) { mkdir($upload_dir, 0755, true);}
// Перемещение загруженного файлаmove_uploaded_file($_FILES['userfile']['tmp_name'], $upload_dir . '/' . $safe_filename);Обработка ошибок и логирование
Заголовок раздела «Обработка ошибок и логирование»Безопасная обработка ошибок
Заголовок раздела «Безопасная обработка ошибок»try { $result = someFunction(); if (!$result) { throw new Exception('Operation failed'); }} catch (Exception $e) { // Логирование ошибки xoops_error($e->getMessage());
// Вывод общего сообщения об ошибке пользователю redirect_header('index.php', 3, 'An error occurred. Please try again later.'); exit();}Логирование событий безопасности
Заголовок раздела «Логирование событий безопасности»// Логирование событий безопасностиxoops_loadLanguage('logger', 'mymodule');$GLOBALS['xoopsLogger']->addExtra('Security', 'Failed login attempt for user: ' . $username);Безопасность конфигурации
Заголовок раздела «Безопасность конфигурации»Сохранение конфиденциальной конфигурации
Заголовок раздела «Сохранение конфиденциальной конфигурации»// Определение пути конфигурации вне веб-корня$config_path = XOOPS_VAR_PATH . '/configs/mymodule/config.php';
// Загрузка конфигурацииif (file_exists($config_path)) { include $config_path;} else { // Обработка отсутствующей конфигурации}Защита файлов конфигурации
Заголовок раздела «Защита файлов конфигурации»Используйте .htaccess для защиты файлов конфигурации:
# В .htaccess<Files "config.php"> Order Allow,Deny Deny from all</Files>Библиотеки третьих сторон
Заголовок раздела «Библиотеки третьих сторон»Выбор библиотек
Заголовок раздела «Выбор библиотек»- Выбирайте активно поддерживаемые библиотеки
- Проверяйте на уязвимости безопасности
- Убедитесь, что лицензия библиотеки совместима с XOOPS
Обновление библиотек
Заголовок раздела «Обновление библиотек»// Проверка версии библиотекиif (version_compare(LIBRARY_VERSION, '1.2.3', '<')) { xoops_error('Please update the library to version 1.2.3 or higher');}Изоляция библиотек
Заголовок раздела «Изоляция библиотек»// Загрузка библиотеки контролируемым способомfunction loadLibrary($file){ $allowed = ['parser.php', 'formatter.php'];
if (!in_array($file, $allowed)) { return false; }
include_once XOOPS_ROOT_PATH . '/modules/mymodule/libraries/' . $file; return true;}Тестирование безопасности
Заголовок раздела «Тестирование безопасности»Контрольный список ручного тестирования
Заголовок раздела «Контрольный список ручного тестирования»- Тестируйте все формы с неправильными входными данными
- Попытайтесь обойти аутентификацию и авторизацию
- Протестируйте функцию загрузки файлов с вредоносными файлами
- Проверьте на XSS уязвимости во всём выводе
- Протестируйте на SQL инъекции во всех запросах к базе данных
Автоматизированное тестирование
Заголовок раздела «Автоматизированное тестирование»Используйте автоматизированные инструменты для сканирования уязвимостей:
- Инструменты статического анализа кода
- Сканеры веб-приложений
- Проверки зависимостей для библиотек третьих сторон
Экранирование выходных данных
Заголовок раздела «Экранирование выходных данных»Контекст HTML
Заголовок раздела «Контекст HTML»// Для обычного HTML-контентаecho htmlspecialchars($variable, ENT_QUOTES, 'UTF-8');
// Использование MyTextSanitizer$myts = MyTextSanitizer::getInstance();echo $myts->htmlSpecialChars($variable);Контекст JavaScript
Заголовок раздела «Контекст JavaScript»// Для данных, используемых в JavaScriptecho json_encode($variable);
// Для встроенного JavaScriptecho 'var data = ' . json_encode($variable) . ';';Контекст URL
Заголовок раздела «Контекст URL»// Для данных, используемых в URLecho htmlspecialchars(urlencode($variable), ENT_QUOTES, 'UTF-8');Переменные шаблона
Заголовок раздела «Переменные шаблона»// Назначение переменных шаблону Smarty$GLOBALS['xoopsTpl']->assign('title', htmlspecialchars($title, ENT_QUOTES, 'UTF-8'));
// Для HTML-контента, который должен отображаться как есть$GLOBALS['xoopsTpl']->assign('content', $myts->displayTarea($content, 1, 1, 1, 1, 1));Ресурсы
Заголовок раздела «Ресурсы»#security #best-practices #xoops #module-development #authentication #authorization