Если вы столкнулись с ошибкой «истек CSRF-токен» — читайте нашу статью. Из неё вы узнаете, как работает CSRF-token защита, и что делать, если CSRF токен истек.

Что такое CSRF
CSRF (англ. cross-site request forgery) — это межсайтовая подделка запроса. Это атака, которой может подвергаться любой веб-ресурс или веб-приложение. В первую очередь это касается сайтов, которые используют cookies, сертификаты авторизации и браузерную аутентификацию. В результате атаки страдают клиенты и репутация ресурса.
Вредоносный скрипт прячется в коде сайта или обычной ссылке. С помощью него мошенник получает доступ к конфиденциальной информации: платежным реквизитам, логину и паролю, личной переписке. После того как данные “в кармане”, хакер может изменить пароль, указать свой номер телефона или email, перевести деньги на свой счёт и многое другое.
Как работает CSRF-атака
Злоумышленник может использовать фишинговую ссылку — это наиболее распространенный способ обмана. В этом случае атака работает по следующей схеме:
- Злоумышленник создаёт поддельную страницу, очень похожую на оригинальную, и встраивает её в сайт. В коде ссылка может выглядеть так: <a href=“вредоносная ссылка”>Unsubscribe here</a>.
- Пользователь переходит с одной страницы сайта на другую (например, на страницу оплаты) и вместо реальной страницы попадает на поддельную.
- Пользователь совершает действие на странице, например, оплачивает товар или вводит данные авторизации.
- Информация или денежные средства вместо оригинального сервера уходят на сервер мошенника.
CSRF-атаки случаются из-за того, что без специальных настроек сервер не может с точностью в 100% определить, кто именно выполняет действия со стороны пользователя. Он не может проверить, действительно ли на кнопку “оплатить” нажал тот пользователь, который изначально открыл страницу с оплатой. Хакеры активно используют этот люфт в безопасности HTTP-запросов и применяют вредоносные скрипты. Однако от атаки можно защититься с помощью CSRF-токенов.
Что такое CSRF-token и как он работает
В общем понимании токен — это механизм, который позволяет идентифицировать пользователя или конкретную сессию для безопасного обмена информацией и доступа к информационным ресурсам. Токены помогают проверить личность пользователя (например, клиента, который онлайн получает доступ к банковскому счёту). Их используют как вместо пароля, так и вместе с ним. Токен — это в каком-то смысле электронный ключ.
CSRF-token — это максимально простой и результативный способ защиты сайта от CSRF-мошенников. Он работает так: сервер создаёт случайный ключ (он же токен) и отправляет его браузеру клиента. Когда браузер запрашивает у сервера информацию, сервер, прежде чем дать ответ, требует показать ключ и проверяет его достоверность. Если токен совпадает, сессия продолжается, а если нет — прерывается. Токен действителен только одну сессию — с новой сессией он обновляется.
Чтобы получить ответ от сервера, используются разные методы запроса. Условно они делятся на две категории: те, которые не изменяют состояние сервера (GET, TRACE, HEAD), и те, которые изменяют (PUT, PATCH, POST и DELETE). Последние имеют большую CSRF-уязвимость и поэтому должны быть защищены в первую очередь.
При создании и использовании токена должны соблюдаться следующие условия:
-
нахождение в скрытом параметре;
-
генерация с помощью генератора псевдослучайных чисел;
-
ограниченное время жизни (одна сессия);
-
уникальность для каждой транзакции;
-
устойчивый к подбору размер (в битах);
-
невозможно переиспользовать.
Типы токенов
Существует три основных типа токенов по способу генерации:
- Synchronizer Tokens или Anti-CSRF (токены синхронизации). В этом случае инициатором ключа выступает сервер — на нём хранится исходная шифровка. Когда браузер обращается к серверу и предъявляет ему ключ, сервер сравнивает его с исходником и в зависимости от результата продолжает или прерывает сессию.
- Double Submit Cookie (двойная отправка куки). При этом способе токен нигде не хранится. Когда браузер обращается к серверу впервые за сессию, сервер генерирует и передаёт ему ключ в двух формах: через куки и в одном из параметров ответа. При следующих обращениях браузера сервер дважды проверяет правильность ключа — в параметрах и в куках.
- Encrypted Token (зашифрованный токен). Этот способ предполагает, что ключом шифруется какая-то часть информации о клиенте, которая содержится в браузере. При первом запросе браузера сервер получает информацию о пользователе, зашифровывает её и передаёт браузеру токен. При следующем взаимодействии сервер расшифровывает токен и сверяет информацию.
Помимо токенов, для защиты используется флаг Same-Site (большинство браузеров его поддерживает). Он работает напрямую для cookies и позволяет помечать куки конкретного домена. Сервер проверяет, содержатся ли нужные пометки в куках страницы, с которых происходит оплата или вносятся изменения. Если пометок нет — сессия прекращается.
Также в качестве меры защиты на страницах сайта настраивают форму с капчей. Это особенно актуально для страниц смены пароля или совершения денежных транзакций.
«Истек срок действия токена» или «CSRF-значение недопустимо»: что это значит и что делать
Даже при авторизации на сайтах, для которых настроена защита от атак, можно встретить следующие варианты сообщения об ошибке: «Недопустимое CSRF-значение»/«CSRF-токены не совпадают» или «Token expired» (в переводе — срок действия токена истек). Сообщение может отображаться как на английском, так и на русском. Пример ошибки при авторизации на сайте REG.RU:

Обычно ошибка возникает по двум основным причинам:
-
сервер некорректно сгенерировал токен;
-
срок токена истек — пользователь долго не совершал никаких действий на странице.
В обоих случаях исправить проблему поможет перезагрузка страницы — вы запустите новую сессию, а значит, сервер и браузер договорятся о новом рабочем токене. Для этого нажмите на значок обновления страницы:

Иногда ошибка возникает из-за расширений защиты конфиденциальности или плагинов блокировки рекламы (например, Ghostery, UBlock Origin, Blur), которые настроены у пользователя. В этом случае можно отключить расширение. Также можно добавить сайт, на котором появилось сообщение, в список доверенных сайтов.
На примере сайта reg.ru покажем, что для этого нужно:
в Google Chrome
- Откройте настройки Chrome:

- В списке слева выберите Конфиденциальность и безопасность, а затем Файлы cookie и другие данные сайтов.
- Внизу страницы откройте Сайты, которые всегда могут использовать файлы cookie и кликните Добавить.
- Введите «[*.]www.reg.ru» и нажмите Добавить.
- Нажмите Все файлы cookie и данные сайта и удалите все записи, которые связаны с сайтом reg.ru.
- Перезагрузите браузер и выполните операцию повторно.
в Яндекс.Браузер
-
Откройте настройки браузера Яндекс:

- Перейдите на Сайты — Расширенные.
- Кликните Настройки… для первого параметра в списке. Затем на вкладке «Разрешена» введите www.reg.ru и кликните Добавить.
- Добавьте адрес сайта для всех параметров списка по аналогии.
в Safari
- Откройте настройки Safari комбинацией Cmd + , (⌘,).
- Перейдите на вкладку Конфиденциальность и проверьте, что в пункте «Файлы cookie и данные веб-сайтов» не выбрано «Блокировать все файлы cookie». Если это так, снимите настройки.
- Кликните Управление данными веб-сайтов и удалите все записи, которые относятся к www.reg.ru.
- Перезагрузите браузер и выполните операцию повторно.
В некоторых случаях сгенерировать верный токен мешают локальные настройки куки в браузере. Чтобы сессия прошла успешно, достаточно вернуть дефолтные настройки.
Заключение
Успешная атака CSRF позволяет хакеру действовать на сайте от имени другого зарегистрированного посетителя. Чтобы мошенник не добрался до конфиденциальных данных, для сайта нужно настроить один из типов CSRF-токенов. Токены позволяют серверу и браузеру безопасно обмениваться информацией в течение сессии. Однако даже на безопасных сайтах можно столкнуться с ошибкой «токен CSRF истек». В этом нет ничего страшного. Чтобы возобновить подключение, достаточно обновить страницу браузера.
Начиная работать с AJAX в Laravel, я сразу столкнулся с ошибкой «CSRF token mismatch«.

Видно, что POST запрос подвисает с ошибкой 419.
Эта ошибка означает, что отсутствует токен CSRF в тех данных, которые принимаются сайтом. Laravel работает с токеном CSRF, тем самым защищая сайт от подделки межсайтовых запросов. Подробности этого механизма можно прочитать в главе «CSRF-защита» русскоязычной документации Laravel. Там же можно найти, что этот токен нужен не только при работе с формами, но и при отправке запросов AJAX. Для этого в секцию head сайта нужно вписать такую строку:
<meta name="csrf-token" content="{{ csrf_token() }}" />
Для отправки токена на сервер с AJAX запросом, нужно включить такую строку
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')}
В моем рабочем примере это выглядит так:
var nomer = $('#'+theId).attr('data-item');
var datasend = "product_id="+nomer+"&count=1";
$.ajax({
type: "POST",
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
url: "/cart",
data: datasend,
success: function(response) {
}
});
Skip to content

По традиции вы открываете браузер для того, чтобы войти в старый добрый заблокированный Роскомнадзором Инстаграм. Включаете свой любименький VPN в браузере с ПК. Заходите на инстаграм.ком, вводите логин и пароль, а этот несуразный сервис вам отвечает красной ошибкой CSRF token missing or incorrect.
Что делать? Как избавиться? Рассказываем:
- Зайдите на https://www.instagram.com/

- Нажмите F12 чтобы открыть в браузере консоль разработчика для отладки и откройте вкладку Network.
- Обновите страницу (кнопкой F5). В списке событий в колонке Name видим www.instagram.com, жмите на него и перейдите в открывшихся вкладках события во вкладку Response

- Далее необходимо найти токен — нажмите CTRL+F и введите в поле поиска «csrf_token«, найдите данную строку и увидите рядом с ним значение вида wH4pOW2E7zC1AJ21QS4CEIImSOjB5F0c (оно прописано в кавычках после двоеточия — смотрите скрин ниже)

- Скопируйте это значение (полностью всё, что в кавычках) и перейдите в общую вкладку отладчика Application. Откройте пункт Cookies и в нём выберите instagram.com

- Перед вами откроется пустой список-таблица. Нажмите в пустую нижнюю строчку — начнётся добавление нового куки.
- В колонку Name введите csrftoken, а в колонку Value вставьте значение, которое скопировали ранее, и в колонке Secure поставьте галочку

- Всё. В окне браузера введите ваши логин и пароль, повторите вход.
Если всё произведено корректно — вы войдете в ваш аккаунт без проблем.
Мой пример разобран через Яндекс.Браузер, но в Google Chrome всё анало_гично. Ноги б моей в инстаграм больше не сунуть, но иногда приходиться туда заходить по делу.
Если вам инструкция помогла — напишите в комментариях под статьёй. Можете в качестве рекламы написать ссылку на свой инстаграм аккаунт, которому мы помогли войти, это бесплатно.
Количество людей, посчитавших эту новость классной: 1 461
3
Hello I am trying to post data via ajax but i face this error and i am sure that i called CSRF_TOKEN in header section
Header Section :
meta name=»csrf-token» content=»{{ csrf_token() }}»
Route Section :
Route::post(‘cart/data/store/{id}’, [CartController::class, ‘AddToCart’]);
Ajax Code :
function addToCart() {
var product_name = $('#pname').text();
var id = $('#product_id').val();
var color = $('#color option:selected').text();
var size = $('#size option:selected').text();
var quantity = $('#qty').val();
$.ajax({
type:"POST",
dataType:"JSON",
data:{
color:color,
size:size,
quantity:quantity,
product_name:product_name,
},
url: "cart/data/store/"+id,
success:function(data) {
$('#closeModal').click();
console.log(data)
}
})
}
Controller :
class CartController extends Controller
{
public function AddToCart(Request $request, $id) {
$product = Product::findOrFail($id);
if ($product->discount_price == NULL) {
Cart::add([
'id' => $id,
'name' => $request->product_name,
'qty' => $request->quantity,
'price' => $product->selling_price,
'weight' => 1,
'options' => [
'image' => $product->product_thumbnail,
'size' => $request->size,
'color' => $request->color,
],
]);
return response()->json(['success' => 'Item Added To Your Cart']);
} else {
Cart::add([
'id' => $id,
'name' => $request->product_name,
'qty' => $request->quantity,
'price' => $product->discount_price,
'weight' => 1,
'options' => [
'size' => $request->size,
'color' => $request->color,
'image' => $product->product_thumbnail
],
]);
return response()->json(['success' => 'Item Added To Your Cart']);
}
}
}
Token Section :
$.ajaxSetup({
headers:{
'X-CSRF-TOKEN': $('meta[name="csrf_token"]').attr('content')
}