CSRF и токены защиты

CSRF (Cross-Site Request Forgery) заставляет браузер жертвы выполнить действие на сайте, где она уже залогинена, — без её ведома.

Почему это возможно

Когда вы вошли на сайт, браузер хранит сессионную куку и автоматически прикрепляет её ко всем запросам на этот сайт. Если злоумышленник заманит вас на свою страницу, та может отправить запрос на «доверенный» сайт — и браузер послушно приложит вашу куку. Сервер увидит валидную сессию и выполнит действие.

Что отличает CSRF от XSS

CSRF не крадёт данные и не выполняет скрипт на странице жертвы. Он злоупотребляет тем, что аутентификация по куке происходит автоматически. Поэтому защита строится вокруг проверки «а правда ли этот запрос пришёл с нашей формы».

Защита: CSRF-токены

Сервер выдаёт каждой форме секретный одноразовый токен, который чужой сайт не может угадать. При отправке формы токен возвращается, и сервер сверяет его. Чужая страница токена не знает — запрос отклоняется.

import secrets

# Сервер генерирует токен и кладёт его в форму и в сессию
csrf_token = secrets.token_hex(16)
session = {"csrf": csrf_token}

# При получении формы сервер сверяет присланный токен с сохранённым
def check_request(form_token, session):
    return secrets.compare_digest(form_token, session["csrf"])

print("Правильный токен принят:", check_request(csrf_token, session))
print("Подделанный токен принят:", check_request("00000000", session))

Используем compare_digest для сравнения, устойчивого к атакам по времени.

Современные слои защиты

  • CSRF-токены — классика, встроена во фреймворки (Django, Flask-WTF и др.).
  • Куки с атрибутом SameSite (Lax/Strict) — браузер не отправляет куку при межсайтовых запросах.
  • Проверка заголовков Origin / Referer как дополнительный сигнал.

Главное правило: меняющие данные действия (POST/PUT/DELETE) должны требовать подтверждения, которое нельзя подделать с чужого сайта.

Проверьте себя
1. Почему CSRF-атака вообще срабатывает?
AПотому что сайт хранит пароли в открытом виде
BПотому что браузер автоматически прикладывает сессионную куку к запросам на сайт, даже если запрос инициирован чужой страницей
CПотому что HTTPS не работает
DПотому что пользователь сам вводит вредный код
Поддержать проект