Мне кажется, что основная цель CSRF — подтвердить, что клиент, делающий запрос, является тем клиентом, которого мы ожидаем.
Решение, которое я обычно видел, это:
- Сервер генерирует случайный токен CSRF
- Сервер устанавливает токен CSRF в файле cookie
- Server injects the CSRF token into the form when generating the form OR
- Сервер передает токен CSRF в javascript, а javascript вводит токен CSRF в качестве заголовка в XMLHTTPRequests.
- Когда запрос получен, он проверяется путем проверки того, что токен CSRF в файле cookie соответствует токену CSRF в значении заголовка/формы.
Для меня очень важно, что сервер генерирует CSRF для (3)(1), но я не могу придумать причину, по которой это необходимо для (3)(2).
Вместо этого, если клиент представляет собой чистый javascript, я считаю, что это безопасно:
- Javascript генерирует случайный токен CSRF
- Javascript устанавливает токен CSRF в файле cookie
- Javascript передает токен CSRF в заголовке при создании XMLHTTPRequest
- Сервер проверяет, что токен CSRF в заголовке и файле cookie совпадают.
Насколько я понимаю, 3 и 4 - это то, что злоумышленник не может сделать, поэтому это также будет достаточно блокировать атаки. Это правильно?
Если это безопасно, нужно ли нам вообще выполнять шаги (1) и (2)? Будет ли это также безопасно из-за политики одного и того же происхождения (при условии, что cors настроен правильно)?
- Javascript устанавливает заголовок «CSRF-Safe: true» в XMLHTTPRequest
- Сервер проверяет, что заголовок CSRF-Safe существует и имеет значение «true».