Защита от CSRF с помощью веб-токенов JSON
Я читал, что при использовании JWT нет необходимости защищать от CRSF-атак, например: " поскольку вы не полагаетесь на файлы cookie, вам не нужно защищать от межсайтовых запросов".
Однако чего-то я не понимаю: если я храню токен в localStorage (как мне посоветовали на уроке на том же веб-сайте), что мешает злоумышленнику подделать вредоносный запрос, прочитав мой localStorage вместо моих файлов cookie?
Поскольку он был сгенерирован на стороне сервера, я не понимаю, как можно использовать токен для клиентского запроса без его сохранения где-то на клиенте.
2 ответа
Строго говоря, да, все, что хранится в локальном / сессионном хранилище (которое я назову HTML5 Storage), может быть украдено при атаке с использованием межсайтового скриптинга (XSS). Смотрите эту статью.
Однако есть много движущихся частей.
Во-первых, существуют тонкие различия в том, как хранилище HTML5 и файлы cookie используются в отношении доступа к JavaScript.
HTML5 Storage это:
- делится между http и https. Предмет хранится в
http://example.com
Хранилище HTML5 не может быть доступно с помощью JavaScript, запущенного наhttps://example.com
, - разделены между поддоменами. Предмет хранится в
http://example.com
Хранилище HTML5 не может быть доступно с помощью JavaScript, запущенного наhttp://sub.example.com
(Вы можете сделать некоторые трюки, чтобы обойти это, однако).
Печенье более приятное:
- Печенье с доменом
example.com
пойдет на обаhttp://example.com
а такжеhttps://example.com
если он не имеет атрибутаsecure
, в этом случае он будет отправлен толькоhttps
, - Файл cookie, не отправленный с явным доменом, будет отправлен только в тот домен, который его отправил. Если домен явно определен как
example.com
то он будет отправлен обоимexample.com
а такжеsub.example.com
, (Это самая запутанная часть спецификации cookie, к сожалению, см. Эту статью). - Файл cookie может быть прочитан с помощью JavaScript, если он работает на странице с соответствующим доменом (и с учетом
secure
флаг cookie), если cookie не имеетhttpOnly
атрибут, в этом случае JavaScript не сможет его прочитать.
Во-вторых, поскольку файлы cookie помечаются доменом, при отправке запроса на сервер браузер отправляет файлы "все и только" с соответствующим доменом независимо от домена страницы, с которой был создан запрос.
В последней части рассказывается о том, как осуществляется атака CSRF (политика одного и того же происхождения только очень помогает). Страница OWASP на CSRF - хороший ресурс для изучения того, как работают подобные атаки.
Причина хранения токена аутентификации в локальном хранилище и ручного добавления его к каждому запросу защищает от CSRF - это ключевое слово: manual. Поскольку браузер не отправляет этот токен автоматически, если я зайду evil.com
и ему удается отправить POST http://example.com/delete-my-account
, он не сможет отправить мой токен authn, поэтому запрос игнорируется.
Учитывая вышесказанное, использование cookie или HTML5 Storage становится серией компромиссов:
Хранение токена аутентификации в хранилище HTML5 означает:
(-)
Риск его кражи при атаке XSS.(+)
Обеспечивает защиту CSRF.(-)
Необходимо вручную изменять каждый запрос, поступающий на сервер, ограничивая вас веб-приложениями SPA (например, AngularJs).
С другой стороны, если вы храните токен authn в файле cookie с пометкой httpOnly
а также secure
, затем:
(+)
Токен authn не может быть украден XSS.(-)
Вы должны будете обеспечить защиту CSRF самостоятельно. Реализация защиты от CSRF проще в некоторых средах, чем в других.
Какой вариант лучше, зависит от ваших потребностей.
- Защищает ли ваш токен что-либо, связанное с деньгами? Вы, вероятно, захотите печенье
httpOnly
secure
вариант. - Разве уровень усилий, требуемых для реализации защиты CSRF, не стоит активов, которые он защищает? Тогда хранилище HTML5 может быть правильным местом.
При использовании аутентификации на основе токенов необходимо вручную связать токен с запросом. В отличие от файлов cookie, токены не устанавливаются браузером автоматически, поэтому не подвержены csrf
атаки.
Пока этот подход безопасен от csrf
атаки, он подвержен xss
атаки.
Минимальное улучшение усилий было бы использовать session storage
вместо local storage
поскольку session storage
данные удаляются после того, как пользователь закрывает вкладку / браузер.