CSRF защита в маршрутизации

CSRF (Cross-Site Request Forgery) — это тип атаки, при котором злоумышленник заставляет браузер аутентифицированного пользователя выполнять нежелательные действия на сайте, где пользователь имеет права доступа. На уровне маршрутизации в JavaScript это особенно важно, так как маршрутизаторы управляют обработкой запросов и могут выступать точкой контроля доступа к различным ресурсам.

При использовании Universal Router критично учитывать, что маршруты не только направляют запросы на нужные обработчики, но и могут выступать в роли фильтров безопасности. Неправильная конфигурация маршрутов или отсутствие проверки токенов CSRF может позволить атакующему выполнить запрос от имени пользователя без его ведома.


Интеграция CSRF защиты с Universal Router

Universal Router предоставляет абстрактный способ обработки маршрутов на стороне клиента и сервера. Основная стратегия защиты от CSRF заключается в проверке токена в каждом изменяющем состояние запросе (POST, PUT, DELETE). Реализация в контексте Universal Router включает несколько ключевых компонентов:

1. Генерация и хранение CSRF токена

На сервере создаётся уникальный CSRF токен для каждой сессии пользователя. Обычно это случайная строка достаточной длины, например, 128 бит. Токен хранится в сессии или в HTTP-only cookie, а клиент получает его через безопасный канал (например, через HTML мета-тег или через JSON-ответ API).

// Node.js пример генерации токена
const crypto = require('crypto');

function generateCsrfToken() {
  return crypto.randomBytes(16).toString('hex');
}

Важно, чтобы токен был одноразовым или обновлялся регулярно, чтобы снизить риск использования украденного токена.


2. Передача токена клиенту

На клиентской стороне Universal Router может извлекать токен из cookies или мета-тега и включать его в заголовки всех изменяющих состояние запросов.

function getCsrfToken() {
  return document.querySelector('meta[name="csrf-token"]').getAttribute('content');
}

async function postData(url, data) {
  const token = getCsrfToken();
  return fetch(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-CSRF-Token': token
    },
    body: JSON.stringify(data)
  });
}

Здесь ключевой момент: каждый POST-запрос снабжается токеном, что предотвращает его подделку злоумышленником.


3. Валидация токена в маршрутах

На серверной стороне Universal Router может использоваться для обработки как клиентских маршрутов, так и API-запросов. Валидация CSRF токена должна выполняться на этапе разрешения маршрута, до выполнения логики изменения данных.

const routes = [
  {
    path: '/update-profile',
    action: async (context) => {
      const { request } = context;
      const token = request.headers['x-csrf-token'];
      if (!validateCsrfToken(token, request.session)) {
        throw new Error('Invalid CSRF token');
      }
      return updateUserProfile(request.body);
    }
  }
];

Особенности реализации:

  • Проверка должна выполняться только для запросов, которые изменяют состояние (GET обычно не требует CSRF проверки).
  • В случае невалидного токена запрос отклоняется с соответствующим HTTP статусом (403 Forbidden).
  • validateCsrfToken сравнивает токен из запроса с токеном, хранящимся в сессии или cookie.

4. Защита маршрутов с Universal Router на клиенте

Хотя CSRF — серверная угроза, маршрутизация на клиенте тоже влияет на защиту. Universal Router может использовать посредники (middlewares) для проверки состояния перед переходом на маршрут:

function csrfMiddleware(context, next) {
  if (context.request.method !== 'GET') {
    const token = context.request.headers['x-csrf-token'];
    if (!validateCsrfToken(token, context.session)) {
      throw new Error('CSRF token missing or invalid');
    }
  }
  return next();
}

const router = new UniversalRouter(routes, { context: { session } });
router.resolve({ path: '/update-profile', request })
  .then(result => console.log(result))
  .catch(err => console.error(err));

Такой подход позволяет встроить централизованную проверку CSRF в обработку маршрутов, обеспечивая одинаковую защиту для всех изменений состояния приложения.


5. Продвинутые методы защиты

  1. Двухуровневые токены (Double Submit Cookie): токен хранится в cookie и в заголовке запроса; сервер сравнивает их. Уменьшает зависимость от сессий.
  2. SameSite cookie: установка SameSite=Strict или Lax снижает риск автоматического отправления cookie при сторонних запросах.
  3. Регулярная ротация токенов: обновление токена каждые N минут или после выполнения критических действий.
  4. Интеграция с JWT: при использовании токенов доступа CSRF токен может быть частью payload и проверяться вместе с подписью.

6. Практические рекомендации

  • В Universal Router не доверять автоматически любым POST/PUT/DELETE маршрутам, всегда проверять токен.
  • Использовать централизованную функцию валидации, чтобы избежать дублирования логики на каждом маршруте.
  • В случае SPA-приложений, где клиент рендерит маршруты, CSRF токен должен быть доступен и вставлен во все изменяющие состояние fetch-запросы.
  • Тщательно документировать, какие маршруты требуют CSRF защиты, и исключать из неё только безопасные GET-запросы.

Заключение по безопасности маршрутизации

Правильная интеграция CSRF защиты в Universal Router требует согласованной работы сервера и клиента, строгого контроля токенов и правильной обработки маршрутов. Это критически важно для предотвращения подделки запросов и обеспечения безопасного взаимодействия пользователя с приложением.