Skip to content

Как защитить сайт от CSRF

Коротко:

CSRF (Cross-Site Request Forgery) — атака, где злоумышленник заставляет пользователя выполнить action на вашем сайте (перевод денег, изменение пароля) через cross-site request. Mitigation: 1) **SameSite cookie** (default Strict/Lax в 2026 browsers), 2) **CSRF token** в формах (synchronizer token pattern), 3) **Check Origin/Referer** headers. Современные frameworks делают это automatic.

Ниже: пошаговая инструкция, рабочие примеры, типичные ошибки, FAQ.

Пошаговая настройка

  1. Set cookies с SameSite=Lax (default в modern browsers, но явно лучше) + HttpOnly + Secure
  2. Для state-changing forms (POST/PUT/DELETE) — add CSRF token field
  3. Server: generate token per session, store в session, validate на каждый POST
  4. Для JSON API: require custom header (X-CSRF-Token) — simple requests не могут его set без JS
  5. Check Origin/Referer: reject requests с foreign origin для state-changing endpoints
  6. Test: fetch из другого site → должен быть blocked browser CORS + your CSRF check

Рабочие примеры

СценарийКонфиг
PHP session-based token<?php session_start(); if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } // Form: echo '<input type="hidden" name="_token" value="' . $_SESSION['csrf_token'] . '">'; // Validate: if (!hash_equals($_SESSION['csrf_token'], $_POST['_token'] ?? '')) { http_response_code(403); exit('CSRF'); }
Django (auto)# settings.py MIDDLEWARE = ['django.middleware.csrf.CsrfViewMiddleware', ...] # In template: # <form method="post">{% csrf_token %} ... </form>
Express.js (csurf)const csrf = require('csurf'); app.use(csrf({ cookie: true })); app.get('/form', (req, res) => { res.render('form', { csrfToken: req.csrfToken() }); });
SameSite cookieSet-Cookie: session=abc; HttpOnly; Secure; SameSite=Lax # Lax — allows top-level GET, blocks cross-site POST # Strict — blocks всё cross-site (breaks OAuth callbacks)
Origin header check$allowed = ['https://example.com', 'https://www.example.com']; $origin = $_SERVER['HTTP_ORIGIN'] ?? ''; if (!in_array($origin, $allowed)) { http_response_code(403); exit; }

Типичные ошибки

  • Token static — предсказуем, можно угадать. Всегда random per-session
  • Check equality через === — timing attack. Используйте hash_equals()
  • SameSite=Strict breaks OAuth/payment redirects. Use Lax for most cases
  • Cookie без Secure flag + HTTPS mixed content → можно leak в plain HTTP
  • CSRF не защищает от XSS. XSS bypasses CSRF (attacker script reads token). Фиксите XSS тоже
ЗаголовкиCSP, HSTS, X-Frame-Options и др.
SSL/TLSШифрование и сертификат
КонфигурацияСерверные настройки и утечки
Оценка A-FОбщий балл безопасности

Почему нам доверяют

OWASP
рекомендации
15+
заголовков безопасности
<2с
результат
A–F
оценка безопасности

Как это работает

1

Введите URL сайта

2

Анализ заголовков безопасности

3

Получите оценку A–F

Что проверяет анализ безопасности?

Инструмент проверяет HTTP-заголовки безопасности, конфигурацию SSL/TLS, утечки серверной информации и защиту от распространённых атак (XSS, clickjacking, MIMEsniffing). Оценка от A до F показывает общий уровень защиты.

Анализ заголовков

Проверка Content-Security-Policy, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy и других.

Проверка SSL

Версия TLS, срок сертификата, цепочка доверия, поддержка HSTS.

Обнаружение утечек

Поиск раскрытых серверных версий, debug-режимов, открытых конфигов и директорий.

Отчёт с рекомендациями

Детальный отчёт с объяснением каждой проблемы и конкретными шагами для исправления.

Кому это нужно

Специалисты по безопасности

аудит HTTP-заголовков

DevOps

проверка конфигурации

Разработчики

CSP и HSTS настройка

Аудиторы

соответствие стандартам

Частые ошибки

Нет Content-Security-PolicyCSP — главная защита от XSS. Без него инъекция скриптов значительно проще.
Нет заголовка HSTSБез HSTS возможна downgrade-атака с HTTPS на HTTP. Включите Strict-Transport-Security.
Server header раскрывает версиюServer: Apache/2.4.52 помогает атакующим подобрать эксплойт. Скройте версию.
X-Frame-Options не установленСайт можно встроить в iframe для clickjacking-атаки. Установите DENY или SAMEORIGIN.
Нет X-Content-Type-OptionsБез nosniff браузер может интерпретировать файлы неправильно (MIME sniffing).

Лучшие практики

Начните с базовых заголовковМинимум: HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy. Займёт 5 минут.
Внедрите CSP постепенноНачните с Content-Security-Policy-Report-Only, мониторьте нарушения, затем включите.
Скройте серверные заголовкиУдалите Server, X-Powered-By, X-AspNet-Version из ответов.
Настройте Permissions-PolicyОграничьте доступ к камере, микрофону, геолокации — только то, что реально используется.
Проверяйте после каждого деплояЗаголовки безопасности могут быть перезаписаны при обновлении конфигурации сервера.

Получите больше с бесплатным аккаунтом

История security-проверок и мониторинг HTTP-заголовков безопасности.

Зарегистрироваться (FREE)

Больше по теме

Часто задаваемые вопросы

SameSite=Lax достаточно в 2026?

Для top-level GET — да. Для POST/PUT/DELETE — Lax блокирует cross-site, это core CSRF mitigation. Но defence-in-depth: token на state-changing forms обязателен.

API с cookies auth — CSRF нужен?

Да, если cookies. JWT в header (Bearer) — CSRF ok (attacker не может set custom header). Cookies — vulnerable без CSRF token.

SPA + JSON API — как?

Double-Submit Cookie: CSRF token в cookie + в request header. Attacker не может read cookie (SameOrigin), не знает value для header.

Как проверить CSRF защиту?

Create test page на другом domain с <code>fetch('/your-site/action', {method: 'POST', credentials: 'include'})</code>. Должен быть blocked.