Функция 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-токен, защищая систему от внешних атак. В данном коде функция вызывается в самом начале выполнения логики выхода, чтобы при недействительном запросе дальнейшие действия не производились. Это соответствует принципу "проверяй сначала — исполняй потом".

7 минут чтения Administrator

Комментарии (0)

Комментарии отсутствуют
Добавление комментариев доступно только зарегистрированным пользователям

Автор контента

Administrator

Оффлайн

Administrator

Последняя авторизация: 05.07.2026 18:32

  • Страница размещена: 23.01.2025 09:55
  • Последнее обновление: 23.01.2025 10:11