Что такое CSRF-токен и как он защищает от атак?

«Что такое CSRF-токен и как он защищает от атак?» — вопрос из категории Безопасность, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Как работает защита:

  1. Сервер генерирует токен и привязывает его к сессии пользователя
  2. Токен встраивается в HTML-формы как скрытое поле или добавляется в заголовки
  3. При получении POST/PUT/DELETE запроса сервер сравнивает токен из запроса с токеном в сессии
  4. Запрос без валидного токена отклоняется

Пример реализации в Spring Security:

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                // Исключение API endpoints, если нужно
                .ignoringRequestMatchers("/api/public/**")
            );
        return http.build();
    }
}

В Thymeleaf форме токен добавляется автоматически:

<form method="post" action="/transfer">
    <!-- Thymeleaf автоматически добавит скрытое поле с токеном -->
    <input type="hidden" name="amount" value="1000">
    <input type="hidden" name="toAccount" value="12345">
    <button type="submit">Перевести деньги</button>
</form>
<!-- Сгенерирует: <input type="hidden" name="_csrf" value="a1b2c3d4..."> -->

Для AJAX-запросов:

// Получаем токен из cookie или meta-тега
const csrfToken = document.querySelector('meta[name="_csrf"]').content;
const csrfHeader = document.querySelector('meta[name="_csrf_header"]').content;

// Добавляем в заголовок
fetch('/api/update', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        [csrfHeader]: csrfToken  // Например: 'X-CSRF-TOKEN': 'a1b2c3d4'
    },
    body: JSON.stringify(data)
});

Важные особенности:

  • Токен должен быть непредсказуемым и уникальным для сессии
  • Используется только для защиты аутентифицированных запросов
  • Не защищает от XSS — если злоумышленник может выполнить JavaScript, он может украсть токен
  • SameSite cookie attribute — дополнительная защита на уровне браузера