В этой главе рассматриваются встроенные механизмы обеспечения безопасности Seditio CMS (фильтрация ввода, защита от CSRF/XSS и SQL-инъекций), а также инструменты кэширования и оптимизации работы с базой данных для повышения быстродействия сайта.
9.1. Фильтрация входящих данных (sed_import)
В Seditio CMS действует принцип: «никогда не доверяй входящим данным». Любая переменная, получаемая из внешних источников (запросы GET, POST, файлы Cookie), перед использованием должна быть импортирована и очищена с помощью системной функции sed_import() (описана в system/functions.php).
9.1.1. Сигнатура и назначение параметров
Функция имеет следующую структуру:
function sed_import($name, $source, $filter, $maxlen = 0, $dieonerror = false)
$name(string) — имя импортируемой переменной (ключ в массивах$_GET,$_POSTили$_COOKIE).$source(string) — источник данных (откуда считывать значение).$filter(string) — тип применяемого фильтра очистки.$maxlen(int, необязательный) — ограничение максимальной длины строки. Если значение превышает$maxlen(и$maxlen > 0), строка автоматически обрезается с помощью мультибайтовой функцииmb_substr(). По умолчанию —0(без ограничений).$dieonerror(bool, необязательный) — флаг критической обработки. Если равенtrueи переданное значение не проходит валидацию выбранным фильтром, скрипт немедленно прекращает выполнение с выводом ошибкиsed_diefatal('Wrong input.'). По умолчанию —false.
9.1.2. Источники входящих данных
Параметр $source принимает одно из четырёх строковых значений:
'G'— данные считываются из глобального массива$_GET.'P'— данные считываются из глобального массива$_POST.'C'— данные считываются из глобального массива$_COOKIE.'D'— прямое использование значения (DIRECT). В этом случае в качестве$nameпередается готовая PHP-переменная, которую требуется просто отфильтровать по заданным правилам.
9.1.3. Справочник фильтров очистки
В зависимости от ожидаемого типа данных, параметр $filter может принимать следующие значения:
| Фильтр | Описание логики очистки и валидации |
|---|---|
INT | Проверяет, является ли значение целым числом. При успешной валидации приводит значение к типу (int). |
NUM | Проверяет, является ли значение числовым. Приводит к числу с плавающей точкой или целому ($v + 0). |
TXT | Безопасный текст. Если строка содержит символ <, она автоматически экранируется через htmlspecialchars($v, ENT_QUOTES, 'UTF-8'). |
SLU | ЧПУ-слаг. Разрешает только латинские символы, цифры, знаки подчеркивания, дефисы, знаки равенства и слэш: a-zA-Z0-9_\-=/. Все остальные символы вырезаются. |
ALP | Только алфавитные символы. Очищает строку от любых символов, кроме латинских букв (использует вспомогательную функцию sed_alphaonly()). |
ALS | Заголовки и имена. Разрешает буквы, цифры, пробелы и дефисы. Любые другие символы заменяются знаком подчеркивания _. |
PSW | Безопасный пароль. Вырезает кавычки (', "), знак амперсанда (&) и угловые скобки (<, >). Максимальная длина жестко ограничивается 32 символами. |
H32 | Хэш (например, MD5). Разрешает только латинские буквы и цифры. Длина обрезается до 32 символов. |
HTR | Доверенный HTML (HTML Trusted). Строка возвращается без какой-либо фильтрации в исходном виде. Применяется только для контента от администраторов. |
HTM | HTML-код, подлежащий обработке плагинами очистки через хук import.filter (например, плагином HTMLPurifier). |
ARR | Массив. Возвращает массив без изменений. Фильтрация элементов должна выполняться вручную. |
BOL | Булево значение. Если значение равно '1', 'on', true или 1, возвращает true. Для '0', 'off', false или 0 возвращает false. Во всех остальных случаях возвращает false. |
LVL | Уровень пользователя. Числовое значение строго от 0 до 100. |
NOC | Без проверки (No Check). Возвращает сырую строку без изменений. |
9.1.4. Логика обработки некорректных значений
Если входящее значение не проходит проверку регулярным выражением или условием фильтра:
- Выполняется автоматическая запись инцидента в журнал безопасности с помощью функции
sed_log_sed_import(). - Если
$dieonerrorравенtrue, выполнение прерывается фатальной ошибкой. - Если выполнение продолжается, функция возвращает безопасное значение по умолчанию (для большинства строковых фильтров возвращается предварительно очищенная строка, для
BOL—false, для числовых —null).
Пример безопасного импорта параметров в коде модуля:
// Безопасное получение ID страницы (GET)
$id = sed_import('id', 'G', 'INT');
// Безопасное получение текста комментария (POST)
$text = sed_import('rtext', 'P', 'TXT', 1000);
// Безопасный импорт с аварийным завершением
$category = sed_import('c', 'G', 'SLU', 64, true);
9.2. Защита от CSRF и XSS-атак
Межсайтовая подделка запроса (CSRF) — атака, при которой пользователя заставляют выполнить нежелательные действия на веб-ресурсе, где он авторизован. Seditio CMS блокирует эти атаки с помощью токенизации запросов.
9.2.1. Генерация токена безопасности (sed_sourcekey)
При инициализации сеанса в файле system/common.php для каждого посетителя генерируется уникальный сессионный ключ:
- Для гостей: Создается случайный MD5-хэш с помощью функции
sed_unique()и записывается в сессию:$_SESSION['guest_sourcekey'] = md5(sed_unique(16));
- Для авторизованных пользователей: Ключ генерируется динамически на основе секретного индивидуального ключа пользователя и времени его последнего визита:
$usr['sourcekey'] = md5($row['user_secret'] . $row['user_lastvisit']);
Функция sed_sourcekey() в system/functions.php считывает этот ключ, берет первые 6 символов, приводит к верхнему регистру (для гостей добавляется префикс GUEST_) и возвращает полученный токен.
9.2.2. Защита GET-запросов (sed_check_xg)
Любые действия, изменяющие состояние системы через GET-запросы (например, удаление страницы, очистка кэша, переключение статуса), должны сопровождаться проверочным параметром x в URL:
<a href="index.php?module=page&m=delete&id=5&x={PHP.sys.xg}">Удалить страницу</a>
При обработке этого запроса контроллер ядра в обязательном порядке вызывает валидатор:
sed_check_xg(); // Сравнит $_GET['x'] с токеном sed_sourcekey() и прервет работу при несовпадении
9.2.3. Защита POST-форм (sed_check_xp)
Все POST-формы на сайте должны передавать токен безопасности в скрытом поле x. В HTML-шаблоне:
<form action="index.php?module=comments&m=add" method="post">
<input type="hidden" name="x" value="{PHP.sys.xp}" />
<textarea name="rtext"></textarea>
<button type="submit">Отправить</button>
</form>
В PHP-контроллере обработчика:
sed_check_xp(); // Защитит форму от отправки сторонними скриптами
9.2.4. Безопасность AJAX-вызовов (sed_check_csrf)
При выполнении асинхронных AJAX-запросов токен безопасности передается в HTTP-заголовке X-Seditio-CSRF. На стороне сервера валидация выполняется с помощью функции sed_check_csrf():
if (!sed_check_csrf()) {
sed_diefatal('Invalid CSRF token for AJAX request.');
}
9.3. Защита от SQL-инъекций
SQL-инъекция — атака, при которой внедряется вредоносный SQL-код во входящие запросы к базе данных.
9.3.1. Экранирование через sed_sql_prep
Для подготовки строковых значений перед их вставкой в SQL-запрос используется функция sed_sql_prep() (или встроенные методы экранирования СУБД):
function sed_sql_prep($string)
Она экранирует спецсимволы SQL (одинарные кавычки, управляющие символы) для предотвращения выхода за границы SQL-контекста.
9.3.2. Рекомендации по написанию безопасных запросов
- Числовые параметры: Все числовые переменные должны принудительно преобразовываться к типу
(int)или(float)либо импортироваться через фильтрINT/NUM:// БЕЗОПАСНО: $id = (int)$id; $sql = sed_sql_query("SELECT * FROM $db_pages WHERE page_id = $id"); - Строковые параметры: Все строки должны оборачиваться в
sed_sql_prep()и помещаться внутри запроса в одинарные кавычки:// БЕЗОПАСНО: $title = sed_sql_prep($title); $sql = sed_sql_query("SELECT * FROM $db_pages WHERE page_title = '$title'");
[!CAUTION] Прямая склейка строк: Никогда не вставляйте нефильтрованные глобальные массивы (
$_GET,$_POST) напрямую в SQL-запрос. Запросы видаSELECT * FROM table WHERE field = '.$_GET['val'].'категорически запрещены и представляют критическую уязвимость!
9.4. Оптимизация производительности и кэширование
Для снижения нагрузки на сервер базы данных и ускорения отдачи страниц в Seditio CMS реализована гибридная система кэширования.
9.4.1. Встроенное кэширование в базу данных (DB Cache)
Включение кэширования производится в панели администратора (раздел «Конфигурация» → «Главные настройки» → «Внутренний Кэш»), после чего ядро сохраняет статус $cfg['cache'] = 1 в системной таблице конфигураций (sed_config). В PHP-коде текущее состояние кэширования считывается из глобального массива конфигурации $cfg['cache']. При включенной опции система сохраняет ресурсоемкие результаты (например, списки меню, облака тегов, результаты работы плагинов) в системную таблицу базы данных $db_cache (обычно sed_cache).
Для управления кэшем используются следующие функции:
sed_cache_store($name, $value, $expire, $auto = 1)— сохраняет значение под уникальным именем$name.$value— любые структуры данных (массивы, объекты, строки), которые внутри автоматически сериализуются черезserialize().$expire— время жизни кэша в секундах.$auto— флаг автозагрузки (описан ниже).
sed_cache_get($name, $expire = true)— извлекает данные из кэша. Если срок жизни кэша истек (и параметр$expireравенtrue), функция вернетfalse.sed_cache_clear($name)— удаляет конкретную запись кэша по имени.sed_cache_clearall()— полностью очищает всю таблицу кэша.
9.4.2. Механизм автозагрузки кэша (c_auto)
Для минимизации обращений к базе данных при загрузке каждой страницы Seditio CMS использует оптимизацию автозапускаемых кэшей. При записи кэша с флагом $auto = 1 запись помечается в БД. Во время инициализации ядра в файле system/common.php выполняется один групповой SQL-запрос:
SELECT c_name, c_value FROM sed_cache WHERE c_auto = 1
Все полученные данные десериализуются и импортируются в глобальную оперативную память PHP за один шаг. После этого вызовы sed_cache_get() для автозагружаемых элементов выполняются мгновенно без создания новых SQL-запросов к серверу БД.
9.4.3. Оптимизация клиентского вывода (cleanup)
На уровне шаблонизатора реализована опция базовой очистки и нормализации пробельных символов в HTML-страницах перед их отдачей клиенту. При активации свойства cleanupEnabled (через статический конфигуратор XTemplate::configure()):
- У каждой строки результирующего HTML удаляются пробелы и табуляции в начале и в конце.
- Переносы строк и символы табуляции вокруг HTML-тегов (
<и>) преобразуются или вырезаются для слияния разметки в единый поток. - Множественные пробелы в тексте и внутри тегов (между атрибутами) сжимаются в один пробел.
[!WARNING] Отсутствие специализированной минификации: Метод
cleanup()не производит удаление HTML-комментариев и не сжимает inline JavaScript/CSS по правилам минификации. Поскольку переносы строк удаляются вокруг тегов и сжимаются в тексте, использование однострочных JavaScript-комментариев вида//может привести к синтаксическим ошибкам (весь последующий код склеится в комментируемую строку). В inline-скриптах шаблонов рекомендуется использовать исключительно блочные комментарии/* ... */.
Comments: (0)