Ответ
CSRF (Cross-Site Request Forgery) — это вид атаки на веб-приложения, при которой злоумышленник заставляет браузер авторизованного пользователя выполнить нежелательный запрос к доверенному сайту. Атака возможна, потому что браузер автоматически отправляет cookies (включая сессионные) при каждом запросе к домену.
Сценарий атаки:
- Пользователь авторизуется на сайте
bank.com. Его сессия сохраняется в cookie. - Пользователь переходит на вредоносный сайт, который содержит скрытую форму или отправляет AJAX-запрос на
bank.com/transfer?to=attacker&amount=1000. - Браузер автоматически прикрепляет cookies сессии к этому запросу.
- Сервер
bank.comвидит валидную сессию и выполняет перевод.
Основной метод защиты — CSRF-токены: Сервер генерирует уникальный, секретный токен для каждой пользовательской сессии и внедряет его в формы (как скрытое поле) или в заголовки AJAX-запросов. При получении запроса на изменение состояния сервер проверяет соответствие токена из запроса токену в сессии.
Пример реализации защиты на PHP:
// 1. Генерация и сохранение токена в сессии при её старте
session_start();
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
// 2. Внедрение токена в HTML-форму
<form action="/transfer.php" method="POST">
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($_SESSION['csrf_token'], ENT_QUOTES); ?>">
<!-- остальные поля формы -->
</form>
// 3. Проверка токена при обработке POST-запроса
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'] ?? '')) {
http_response_code(403);
die('Invalid CSRF token.');
}
// Токен верный, обрабатываем запрос
}
Важные моменты:
- Используйте криптографически безопасные генераторы (
random_bytes()). - Проверяйте с помощью
hash_equals()для защиты от атак по времени. - В современных фреймворках (Laravel, Symfony, Django, Spring Security) защита от CSRF встроена и включается по умолчанию.
Ответ 18+ 🔞
Давай разжую эту тему, как будто мы на кухне сидим и я тебе объясняю, почему твой сайт могут обчистить, пока ты в туалете сидишь.
Представь себе такую картину. Ты залогинился в свой интернет-банк, сессия живая, кукисы в браузере тусуются. Всё спокойно. А потом ты, такой довольный, переходишь по ссылке на какой-нибудь форум, где тебе картинку с котиком обещали. А там, ёпта, не котик, а скрытая форма, которая в тихую, пока ты не видишь, шлёт запрос твоему же банку: «Перевести все деньги на счёт злоумышленника». И браузер твой, такой преданный пёс, автоматом цепляет к этому запросу твои же куки с сессией. Банк видит: «А, это наш Вася! Сессия валидная. Переводим!» И всё, приехали. Это и есть CSRF — подделка межсайтовых запросов. Овердохуища рисков, правда?
Короче, злодей может заставить твой браузер сделать что-то на доверенном сайте без твоего ведома. Волнение ебать просто, когда осознаёшь.
Что делать? Основной щит — это CSRF-токены. Суть проста, как три копейки: сервер выдаёт для каждой сессии свой секретный ключ-пароль (токен) и прячет его в форму. Когда форма отправляется назад, сервер сверяет: «А тот ли это самый Вася?». Если токен не совпал или его нет — запрос посылается на три весёлые буквы.
Смотри, как это в коде выглядит, на примере голого PHP. Подозрение ебать чувствую, что многие до сих пор так и пишут.
// 1. Запускаем сессию и генерируем токен, если его ещё нет.
// Без этого — вообще никуда.
session_start();
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32)); // Криптографически безопасно, не костыли!
}
// 2. Встраиваем этот токен в каждую форму, как скрытое поле.
// Если этого не сделать — всё, манда с ушами, защита не работает.
<form action="/transfer.php" method="POST">
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($_SESSION['csrf_token'], ENT_QUOTES); ?>">
<!-- А тут уже твои обычные поля: сумма, счёт и т.д. -->
</form>
// 3. Когда форма прилетела, ПЕРВЫМ ДЕЛОМ проверяем токен.
// Не после того как деньги уже перевели, а сразу!
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'] ?? '')) {
http_response_code(403); // Отказано!
die('Invalid CSRF token. Иди отсюда.');
}
// Только если токен сошёлся — делаем опасные операции (перевод, смену пароля).
}
Важные моменты, на которых все обламываются:
random_bytes()— это твой друг. Неrand(), неmt_rand(), а именно он. Иначе токен угадают, и будет вам хиросима и нигерсраки.hash_equals()— для сравнения. Она от атак по времени защищает, чтобы по скорости ответа не догадались, где ошибка.- В современных фреймворках типа Laravel, Django или Spring Security эта защита уже встроена и включена по умолчанию. Но это не значит, что её нельзя случайно впендюрить себе в проект, отключив одной галочкой. Доверия ебать ноль к настройкам по умолчанию — всегда проверяй!
Запомни главное: если на твоём сайте есть действие, которое меняет состояние (перевод денег, пост в блог, смена почты), и оно работает по авторизованной сессии — ты ходишь по охуенно тонкому льду без CSRF-токена. Любой школьник с полчаса времени может написать страничку, которая обчистит твоих пользователей. Не будь распиздяем, ставь защиту.