CSRF защита

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


Принципы CSRF-защиты

  1. Токены CSRF Основной метод защиты заключается в использовании уникального токена, который сервер генерирует для каждой сессии или формы. Этот токен должен передаваться вместе с каждым изменяющим состояние запросом (POST, PUT, DELETE) и проверяться на сервере.

    • Токен можно хранить в cookie с атрибутом HttpOnly или передавать через скрытое поле формы.
    • Сервер сравнивает полученный токен с тем, что хранится в сессии, и отклоняет запросы с некорректным токеном.
  2. SameSite cookie Атрибут SameSite для cookie ограничивает их отправку только с запросами с того же домена. Настройка Strict или Lax снижает риск CSRF.

    • Strict — cookie отправляется только для прямых переходов на сайт.
    • Lax — cookie отправляется при переходах с безопасных методов (GET), но блокирует небезопасные запросы.
  3. Проверка Referer и Origin Сервер может дополнительно проверять заголовки Referer и Origin, чтобы убедиться, что запрос приходит с доверенного источника.


Подходы к тестированию CSRF с Cypress

Cypress — инструмент для end-to-end тестирования, который отлично подходит для проверки как функциональности, так и безопасности приложений. Основные подходы к тестированию CSRF:

  1. Валидация токена CSRF Необходимо убедиться, что приложение корректно генерирует токен для каждой сессии и валидирует его при изменении состояния. Примерный алгоритм теста:

    describe('CSRF token validation', () => {
      it('rejects requests with missing or invalid CSRF token', () => {
        cy.request({
          method: 'POST',
          url: '/api/update-profile',
          body: { name: 'Test User' },
          failOnStatusCode: false
        }).then((response) => {
          expect(response.status).to.eq(403)
        })
      })
    
      it('accepts requests with valid CSRF token', () => {
        cy.visit('/profile')
        cy.get('input[name="csrf_token"]').then(($input) => {
          const token = $input.val()
          cy.request({
            method: 'POST',
            url: '/api/update-profile',
            body: { name: 'Test User', csrf_token: token }
          }).then((response) => {
            expect(response.status).to.eq(200)
          })
        })
      })
    })
  2. Проверка SameSite cookie Cypress позволяет читать и проверять cookie, что удобно для контроля настроек безопасности:

    cy.getCookie('session_id').should('have.property', 'sameSite', 'Strict')
  3. Симуляция внешних запросов Для проверки, что сервер корректно блокирует сторонние запросы, можно использовать cy.request() с изменением заголовков Origin или Referer:

    cy.request({
      method: 'POST',
      url: '/api/delete-account',
      headers: { Origin: 'https://malicious.com' },
      body: { userId: 123 },
      failOnStatusCode: false
    }).then((response) => {
      expect(response.status).to.eq(403)
    })

Особенности автоматизации CSRF-тестов

  • Динамическое получение токена Токен CSRF часто меняется при каждой загрузке страницы, поэтому его необходимо получать программно перед отправкой запросов.
  • Изоляция тестов Каждое тестовое действие должно выполняться в отдельной сессии или с очисткой куки, чтобы избежать влияния предыдущих тестов.
  • Обработка ошибок Cypress по умолчанию завершает тест при статусах 4xx или 5xx. Для CSRF-тестирования важно отключить failOnStatusCode для проверки отклоненных запросов.
  • Сценарии обхода CSRF Тесты могут проверять, что попытки обхода через модификацию заголовков или форм без токена блокируются сервером.

Лучшие практики при тестировании

  • Комбинация UI- и API-тестов Проверка CSRF только через UI может быть недостаточной. API-запросы напрямую позволяют имитировать атаки и выявлять потенциальные уязвимости.
  • Регулярное обновление токена Для приложений с длительными сессиями необходимо убедиться, что токен обновляется и не истекает слишком поздно, иначе защита будет неэффективной.
  • Логирование и мониторинг отказов Тесты должны фиксировать случаи отклонения запросов и корректно их логировать для анализа.

CSRF-тестирование с Cypress позволяет не только выявлять уязвимости, но и формировать стандарты безопасной работы приложения. Благодаря возможности взаимодействия с формами, cookie и заголовками, можно создавать комплексные сценарии, имитирующие реальные атаки, и обеспечивать корректную защиту на всех уровнях.