Функция cot_check_xg в Cotonti
Разбор функции cot_check_xg (в контексте логики Cotonti CMF)
Назначение функции
Эта функция проверяет GET-параметр x, который используется как токен для защиты от XSS-атак. Если значение токена не совпадает с ожидаемым, функция может либо перенаправить пользователя на сообщение об ошибке, либо вернуть false.
Код с подробными комментариями
/**
* Checks GET anti-XSS parameter
*
* @param bool $redirect Redirect to message on failure
* (Перенаправить ли на сообщение об ошибке в случае неудачи)
* @return bool
* (Возвращает true, если проверка токена прошла успешно, и false, если нет)
*/
function cot_check_xg($redirect = true)
{
// Получаем значение GET-параметра 'x', ожидается, что это строка (ALP = alphanumeric string)
$x = cot_import('x', 'G', 'ALP');
// Проверяем, совпадает ли полученный токен $x с текущим значением Cot::$sys['xk']
// Либо с предыдущим значением Cot::$sys['xk_prev'] (если оно задано).
if ($x != Cot::$sys['xk'] && (empty(Cot::$sys['xk_prev']) || $x != Cot::$sys['xk_prev'])) {
// Если токены не совпадают и параметр $redirect равен true,
// то вызывается функция cot_die_message, которая отображает сообщение об ошибке.
if ($redirect) {
cot_die_message(950, TRUE); // Код ошибки 950 — стандартная ошибка XSS
}
// Если $redirect = false, возвращаем false (проверка токена провалилась).
return false;
}
// Если токен валиден, возвращаем true.
return true;
}
Разбор ключевых моментов функции
Получение GET-параметра x:
Функция использует cot_import для безопасного извлечения GET-параметра.
Тип фильтрации 'ALP' означает, что допустимы только буквы и цифры (альфанумерические строки). Это предотвращает инъекцию опасных символов.
Проверка токена:
Значение токена x сравнивается с текущим значением Cot::$sys['xk'], которое генерируется системой Cotonti для защиты от XSS.
Также предусмотрена проверка на предыдущее значение токена Cot::$sys['xk_prev'], которое может использоваться для переходных состояний (например, если страница обновляется после смены токена).
Обработка ошибки:
Если токены не совпадают, вызывается функция cot_die_message(950, TRUE), которая перенаправляет пользователя на страницу с сообщением об ошибке.
Код ошибки 950 обычно связан с попыткой XSS-атаки.
Возвращение результата:
Если токен валиден, функция возвращает true.
Если токен не прошёл проверку и перенаправление не требуется ($redirect = false), возвращается false.
Особенности в контексте Cotonti CMF
Использование cot_import:
Эта функция — стандартный метод в Cotonti для безопасного извлечения пользовательских данных. Она проверяет тип данных (в данном случае, альфанумерическая строка) и фильтрует нежелательные символы.
Глобальные переменные:
Cot::$sys['xk'] и Cot::$sys['xk_prev'] — системные переменные, которые управляют текущим и предыдущим токенами для защиты от XSS.
Работа с хуками:
Функция может быть использована в хуках для проверки токенов, например, при обработке форм.
cot_die_message:
Это стандартный метод Cotonti для отображения сообщений об ошибке с возможностью завершить выполнение скрипта.
Пример применения функции
Проверка токена в обработке формы:
if (!cot_check_xg()) {
// Токен недействителен, пользователь перенаправлен на страницу с ошибкой 950.
exit;
}
// Если токен валиден, продолжаем обработку данных.
Проверка без перенаправления:
if (!cot_check_xg(false)) {
echo "Invalid token. Action aborted.";
exit;
}
Итог
Функция cot_check_xg является важной частью механизма безопасности Cotonti. Она защищает сайт от XSS-атак, проверяя уникальный токен в GET-запросах. Использование cot_import и проверка токенов через системные переменные гарантирует защиту данных и предотвращение манипуляций со стороны пользователя.
Разбор кода с использованием функции cot_check_xg на реальном примере в Cotonti CMF
// Настройка переменных окружения для работы с модулем пользователей и страницей входа
Cot::$env['ext'] = 'users'; // Определение текущего модуля как 'users'
Cot::$env['location'] = 'login'; // Установка текущего местоположения (логическая страница) как 'login'
Cot::$sys['sublocation'] = Cot::$L['Login']; // Указание подлокации с использованием языкового файла
// Проверка GET-параметра 'out' для выхода из системы
$logout = cot_import('out', 'G', 'BOL'); // Импорт значения параметра 'out' из GET-запроса как булево значение
if ($logout) {
// Если параметр 'out' установлен, выполняется процесс выхода из системы
cot_check_xg(); // Проверка безопасности XSS через функцию cot_check_xg()
/* === Хук для расширений === */
foreach (cot_getextplugins('users.logout') as $pl) {
include $pl; // Включение подключаемых плагинов для этапа выхода пользователя
}
/* ======================== */
if (Cot::$usr['id'] > 0) {
// Если пользователь авторизован (его ID больше 0), выполняются действия для выхода
cot_uriredir_apply(Cot::$cfg['redirbkonlogout']); // Обработка перенаправления после выхода пользователя
$serverEventsObserverService = ServerEventsObserverService::getInstance();
$serverEventsObserverService->remove(
Cot::$usr['id'], // Удаление наблюдателя событий для текущего пользователя
$serverEventsObserverService->getTokenForCurrentUser() // По токену текущего пользователя
);
}
// Проверка наличия cookie с ID сайта и удаление его, если он существует
if (cot_import(Cot::$sys['site_id'], 'COOKIE', 'TXT')) {
cot_setcookie(
Cot::$sys['site_id'], '', // Установка пустого значения cookie
time() - 63072000, // Истечение срока действия cookie (двухлетний период в прошлом)
Cot::$cfg['cookiepath'], // Путь для cookie
Cot::$cfg['cookiedomain'], // Домен для cookie
Cot::$sys['secure'], // Использование защищённого соединения (HTTPS)
true // Ограничение cookie для HTTP-запросов
);
}
// Удаление всех данных сессии пользователя
session_unset(); // Очистка данных текущей сессии
session_destroy(); // Уничтожение текущей сессии
if (Cot::$usr['id'] > 0) {
// Если пользователь авторизован, обновляется информация о последнем визите
Cot::$db->update(
Cot::$db->users, // Таблица пользователей
['user_lastvisit' => Cot::$sys['now']], // Поле "последний визит" обновляется на текущую дату и время
"user_id = " . Cot::$usr['id'] // Условие: обновить данные только текущего пользователя
);
$all = cot_import('all', 'G', 'BOL'); // Импорт параметра 'all' из GET-запроса как булево значение
if ($all) {
// Если параметр 'all' установлен, пользователь выходит со всех устройств
Cot::$db->update(
Cot::$db->users, // Таблица пользователей
['user_sid' => ''], // Очистка идентификатора сессии для всех устройств
"user_id = " . Cot::$usr['id'] // Условие: обновить данные только текущего пользователя
);
}
// Перенаправление пользователя на указанную страницу или главную, если перенаправление не задано
cot_uriredir_redirect(
empty($redirect) ? cot_url('index') : base64_decode($redirect)
);
} else {
// Если пользователь не авторизован, перенаправление на главную страницу
cot_redirect(cot_url('index'));
}
// Логирование события выхода пользователя
cot_log("Logout user : " . $rusername, 'users', 'logout', 'done');
exit; // Завершение выполнения скрипта
}
Назначение кода
Этот участок кода реализует процесс выхода пользователя из системы (logout). Функция cot_check_xg() используется для проверки безопасности операции выхода, предотвращая возможные XSS-атаки при вызове этого действия через GET-запрос.
Подробный анализ кода
Cot::$env['ext'] = 'users'; Cot::$env['location'] = 'login'; Cot::$sys['sublocation'] = Cot::$L['Login'];
Инициализация переменных среды:
Cot::$env['ext'] указывает на текущий модуль или расширение, в данном случае это модуль users.
Cot::$env['location'] определяет текущее действие (например, login для авторизации).
Cot::$sys['sublocation'] задаёт подлокацию, которая будет использована для генерации навигации или отображения заголовков. Здесь задаётся текст из языкового файла (Cot::$L['Login']).
$logout = cot_import('out', 'G', 'BOL');
Получение параметра out из GET-запроса:
Параметр out указывает на необходимость выхода из системы. Метод cot_import обеспечивает безопасное извлечение данных, а тип BOL (boolean) проверяет, что параметр имеет значение true или false.
Проверка токена через cot_check_xg:
if ($logout) {
// Perform logout
cot_check_xg();
Функция cot_check_xg() проверяет токен x, переданный в GET-запросе, на соответствие ожидаемому значению (Cot::$sys['xk]). Если токен неверен, выполнение прекращается, и отображается сообщение об ошибке.
Это предотвращает XSS-атаки, когда злоумышленник может пытаться вызвать выход пользователя, отправив специально сформированный запрос.
/* === Hook === */
foreach (cot_getextplugins('users.logout') as $pl) {
include $pl;
}
/* ===== */
Вызов хуков:
Этот код выполняет плагины, зарегистрированные для хука users.logout.
Хуки позволяют другим расширениям дополнять или изменять логику выхода без изменения основного кода.
Каждый файл-плагин, возвращённый cot_getextplugins('users.logout'), включается и исполняется.
Обработка выхода авторизованного пользователя:
if (Cot::$usr['id'] > 0) {
cot_uriredir_apply(Cot::$cfg['redirbkonlogout']);
Если текущий пользователь авторизован (Cot::$usr['id'] > 0), применяется перенаправление, определённое в настройках (Cot::$cfg['redirbkonlogout']).
$serverEventsObserverService = ServerEventsObserverService::getInstance();
$serverEventsObserverService->remove(Cot::$usr['id'], $serverEventsObserverService->getTokenForCurrentUser());
Обновление состояния на сервере:
Используется сервис ServerEventsObserverService для удаления сессии или токена текущего пользователя на сервере.
Удаление cookies:
if (cot_import(Cot::$sys['site_id'], 'COOKIE', 'TXT')) {
cot_setcookie(Cot::$sys['site_id'], '', time() - 63072000, Cot::$cfg['cookiepath'],
Cot::$cfg['cookiedomain'], Cot::$sys['secure'], true);
}
Проверяется наличие cookie, идентифицирующего текущую сессию пользователя. Если cookie существует, оно удаляется с помощью cot_setcookie.
session_unset();
session_destroy();
Завершение сессии:
Очищаются и уничтожаются текущие данные сессии, что гарантирует завершение работы пользователя.
Обновление информации пользователя:
if (Cot::$usr['id'] > 0) {
Cot::$db->update(Cot::$db->users, array('user_lastvisit' => Cot::$sys['now']), "user_id = " . Cot::$usr['id']);
if (Cot::$usr['id'] > 0) {
Cot::$db->update(Cot::$db->users, array('user_lastvisit' => Cot::$sys['now']), "user_id = " . Cot::$usr['id']);
В базе данных обновляется поле user_lastvisit, которое фиксирует время последнего посещения пользователя.
Выход со всех устройств:
$all = cot_import('all', 'G', 'BOL');
if ($all) {
// Log out on all devices
Cot::$db->update(Cot::$db->users, array('user_sid' => ''), "user_id = " . Cot::$usr['id']);
}
Если в GET-запросе присутствует параметр all со значением true, выполняется выход пользователя со всех устройств. Это достигается путём сброса user_sid в базе данных.
Перенаправление после выхода:
cot_uriredir_redirect(empty($redirect) ? cot_url('index') : base64_decode($redirect));
} else {
cot_redirect(cot_url('index'));
}
Если задан редирект, перенаправляем пользователя на указанную страницу. В противном случае выполняется редирект на главную страницу.
Логирование и завершение:
cot_log("Logout user : " . $rusername, 'users', 'logout', 'done');
exit;
}
Записывается событие выхода в лог, затем выполнение скрипта завершается.
Место и роль cot_check_xg в коде
Функция cot_check_xg выполняет критически важную проверку безопасности в процессе выхода. Она предотвращает выполнение действия выхода, если запрос не содержит корректный XSS-токен, защищая систему от внешних атак. В данном коде функция вызывается в самом начале выполнения логики выхода, чтобы при недействительном запросе дальнейшие действия не производились. Это соответствует принципу "проверяй сначала — исполняй потом".
Комментарии (0)
Автор контента
Оффлайн
Administrator
Последняя авторизация: 05.07.2026 18:32
- Страница размещена: 23.01.2025 09:55
- Последнее обновление: 23.01.2025 10:11