Что такое CSRF-токен в веб-безопасности?

Ответ

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

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

Принцип работы:

  1. Сервер генерирует уникальный токен при загрузке формы или страницы.
  2. Токен встраивается в форму (как скрытое поле) или передается в HTTP-заголовке (например, X-CSRF-Token).
  3. При отправке формы или AJAX-запроса клиент отправляет токен обратно на сервер.
  4. Сервер проверяет соответствие полученного токена ожидаемому (хранящемуся в сессии пользователя). Если они не совпадают, запрос отклоняется.

Пример реализации в Django:

<!-- В шаблоне Django автоматически вставит CSRF-токен в скрытое поле -->
<form method="post">
    {% csrf_token %}
    <input type="text" name="username">
    <button type="submit">Submit</button>
</form>
# В представлении Django проверит токен автоматически при использовании @csrf_protect или CsrfViewMiddleware
from django.views.decorators.csrf import csrf_protect
from django.shortcuts import render, redirect

@csrf_protect
def my_view(request):
    if request.method == 'POST':
        # Логика обработки формы, если CSRF-токен валиден
        return redirect('success_page')
    return render(request, 'my_form.html')

Ключевые особенности:

  • Уникальность: Генерируется для каждой сессии или формы.
  • Проверка: Сервер проверяет токен при запросах, изменяющих состояние (POST, PUT, DELETE).
  • Хранение: Обычно хранится в куках сессии на стороне клиента и в скрытом поле формы.
  • Защита: Предотвращает выполнение несанкционированных действий от имени пользователя.

Ответ 18+ 🔞

А, ну вот, подъехали к этой теме, блядь! CSRF токен, ёпта! Это ж такая штука, сука, которая не даёт всяким пидарасам с левых сайтов на твоём имени хуйню творить, пока ты в аккаунте сидишь.

Смотри, как это работает, блядь. Представь, ты залогинился в свой банк, допустим. Сессия живая, куки твои браузер таскает. И тут ты, дурак, на какую-то левую ссылку кликнул, а там, блядь, скрытая форма, которая на твой же банк запрос шлёт: «Перевести все деньги на счёт 123». Браузер-то тупой, он куки твои подцепит и отправит, сервер увидит твою сессию и подумает: «А, наш клиент хочет перевести!» И пиздец твоим деньгам, в рот меня чих-пых!

Вот чтобы такого пиздеца не было, умные дядьки и придумали CSRF-токен. Это типа секретный пропуск, который знает только твой родной сайт и твой браузер на конкретной странице. Левая страница его не узнает, не угадает, не спиздит.

Как это, блядь, выглядит на практике:

  1. Ты заходишь на сайт, чтобы форму заполнить. Сервер тебе в ответ, кроме самой формы, подсовывает этот самый токен — уникальный, непредсказуемый, блядь, набор символов. Как пароль на один раз.
  2. Токен этот прячется в форму, как скрытое поле, или в заголовки AJAX-запроса.
  3. Ты форму отправляешь. Вместе с твоими данными («Иванов», «100 рублей») летит и этот токен.
  4. Сервер его получает и сверяет: «А тот ли это пропуск, что я выдал?» Если совпало — ок, выполняем операцию. Если нет — да похуй кто там от имени Иванова просит, в пизду такого гостя! Запрос отбой!

Вот, смотри, как в Django это делается, там вообще красота, всё за тебя сделано:

<!-- В шаблоне просто пишешь эту хуйню, и Django сам всё подставит -->
<form method="post">
    {% csrf_token %} <!-- Вот он, сука, наш спаситель! -->
    <input type="text" name="username">
    <button type="submit">Отправить</button>
</form>

А в коде представления вообще нихуя особого делать не надо, если middleware включена (а она по умолчанию включена). Она сама всё проверит, хитрая жопа.

from django.views.decorators.csrf import csrf_protect
from django.shortcuts import render, redirect

@csrf_protect  # Эта декорация лишний раз убедится, что защита работает
def my_view(request):
    if request.method == 'POST':
        # Если дожили сюда, значит токен сошёлся, можно работать спокойно
        return redirect('success_page')
    return render(request, 'my_form.html')

Короче, запомни раз и нахуй:

  • Зачем? Чтобы только ты со своих легитимных страниц мог отправлять изменяющие запросы (POST, PUT, DELETE). Никакой левый сайт не сможет за тебя это сделать.
  • Где? В каждой форме, что меняет данные. И в AJAX-запросах тоже не забывай его прикреплять, а то будешь потом ебаться с ошибками 403.
  • Как? Сервер генерирует, встраивает в ответ, потом проверяет. Клиент — просто возвращает обратно.

Вот и вся магия, ёпта. Нехитрая, но овердохуища важная. Без неё — как без штанов на улицу выйти, сразу все твои куки разглядят и используют.