Требуется токен CSRF при использовании аутентификации без сохранения состояния (= без сеанса)?

Необходимо ли использовать защиту CSRF, когда приложение использует аутентификацию без сохранения состояния (используя что-то вроде HMAC)?

Пример:

  • У нас есть одностраничное приложение (в противном случае мы должны добавлять токен к каждой ссылке: <a href="...?token=xyz">...</a>.

  • Пользователь аутентифицирует себя с помощью POST /auth. При успешной аутентификации сервер вернет некоторый токен.

  • Токен будет храниться через JavaScript в некоторой переменной внутри одностраничного приложения.

  • Этот токен будет использоваться для доступа к URL с ограниченным доступом, например /admin.

  • Токен всегда будет передаваться внутри заголовков HTTP.

  • НЕТ Http-сессии и НЕТ файлов cookie.

Насколько я понимаю, не должно (?!) быть возможности использовать межсайтовые атаки, потому что браузер не будет хранить токен, и, следовательно, он не может автоматически отправить его на сервер (это то, что произойдет при использовании файлов cookie / Сессия).

Я что-то упускаю?


person Benjamin M    schedule 25.01.2014    source источник
comment
Будьте осторожны с базовой аутентификацией. Многие браузеры автоматически отправляют основные заголовки аутентификации до конца сеанса. Это может сделать базовую аутентификацию такой же уязвимой для CSRF, как аутентификацию cookie.   -  person phylae    schedule 13.05.2015


Ответы (2)


Я нашел некоторую информацию о CSRF +, использующем нет файлов cookie для аутентификации:

  1. https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
    "поскольку вы не полагаетесь на файлы cookie, вам не нужно защищаться от межсайтовых запросов"

  2. http://angular-tips.com/blog/2014/05/json-web-tokens-introduction/
    «Если мы перейдем к файлам cookie, вам действительно понадобится CSRF, чтобы избежать межсайтовых запросов. Это то, о чем мы можем забыть при использовании JWT, как вы увидите». < br /> (JWT = Json Web Token, аутентификация на основе токенов для приложений без сохранения состояния)

  3. http://www.jamesward.com/2013/05/13/securing-single-page-apps-and-rest-services
    «Самый простой способ выполнить аутентификацию, не рискуя уязвимостью CSRF, - просто избегать использования файлов cookie для идентификации пользователя»

  4. http://sitr.us/2011/08/26/cookies-are-bad-for-you.html
    "Самая большая проблема с CSRF заключается в том, что файлы cookie не обеспечивают абсолютно никакой защиты от этого типа атак. Если вы используете аутентификацию файлов cookie, вы также должны принять дополнительные меры для защиты от CSRF. . Самая простая мера предосторожности, которую вы можете предпринять, - убедиться, что ваше приложение никогда не выполняет никаких побочных эффектов в ответ на запросы GET ".

Есть еще много страниц, на которых указано, что вам не нужна защита CSRF, если вы не используете файлы cookie для аутентификации. Конечно, вы все равно можете использовать файлы cookie для всего остального, но избегайте хранить в них что-либо вроде session_id.


Если вам нужно запомнить пользователя, есть 2 варианта:

  1. localStorage: хранилище ключей и значений в браузере. Сохраненные данные будут доступны даже после того, как пользователь закроет окно браузера. Данные недоступны для других веб-сайтов, потому что каждый сайт получает собственное хранилище.

  2. sessionStorage: Также в хранилище данных браузера. Разница в том, что данные удаляются, когда пользователь закрывает окно браузера. Но это все равно полезно, если ваше веб-приложение состоит из нескольких страниц. Итак, вы можете сделать следующее:

    • User logs in, then you store the token in sessionStorage
    • Пользователь нажимает ссылку, которая загружает новую страницу (= настоящая ссылка, без замены содержимого javascript)
    • Вы по-прежнему можете получить доступ к токену с sessionStorage
    • Чтобы выйти из системы, вы можете вручную удалить токен из sessionStorage или дождаться, пока пользователь закроет окно браузера, которое очистит все сохраненные данные.

(для обоих посмотрите здесь: http://www.w3schools.com/html/html5_webstorage.asp)


Существуют ли официальные стандарты аутентификации токенов?

JWT (Json Web Token): я думаю, что это все еще черновик, но он уже используется многими людьми, и концепция выглядит простой и надежной. (IETF: http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-25)
Также доступны библиотеки для множества фреймворков. Просто погуглите!

person Benjamin M    schedule 08.08.2014
comment
Отличное резюме по CSRF! Замечу, что хранение ваших токенов в localStorage или sessionStorage уязвимо для XSS-атак и что данные можно просматривать с помощью скриптов на странице, поэтому, если у вас есть скомпрометированный скрипт, обслуживаемый из CDN, или если в одном из ваших JS-библиотеки, они могут украсть токен из этих мест хранения. См .: stormpath.com/blog / Я считаю, что наиболее безопасным подходом является хранение токена JWT + CSRF в файле cookie, а затем размещение вычисленного JWT с токеном CSRF внутри него в заголовке запроса. - person Aaron Gray; 21.09.2015
comment
Относительно: Самая основная предосторожность, которую вы можете предпринять, - убедиться, что ваше приложение никогда не выполняет никаких побочных эффектов в ответ на запросы GET. Может ли CSRF-атака подделать запрос POST? - person Costa Michailidis; 23.02.2016
comment
В зависимости от серверного приложения это МОЖЕТ быть возможным. Существуют веб-фреймворки, которые используют что-то вроде http://.../someRestResource?method=POST. Таким образом, это в основном запрос GET, но серверное приложение интерпретирует его как запрос POST, поскольку он был настроен на использование параметра method вместо заголовка HTTP. ... Что касается обычных веб-браузеров, они применяют политику одного и того же происхождения и будут выполнять только GET запросы к сторонним серверам. Хотя может быть возможным выполнение POST запросов , если веб-браузер не применяет эти веб-стандарты (ошибка, вредоносное ПО). - person Benjamin M; 24.02.2016
comment
Дополнение к Server Side App: по-прежнему невозможно отправить тело запроса, потому что обычные браузеры не позволяют этого. Однако, если серверное приложение разрешает method=POST, оно также может разрешить body={someJson} переопределить тело запроса по умолчанию. Это действительно плохой дизайн API и крайне рискованный. Хотя, если ваше серверное приложение позволяет http://...?method=POST&body={someJson}, вам действительно следует слишком сильно задуматься о том, что вы там делали, почему и нужно ли это вообще. (Я бы сказал, что в 99,9999% случаев это не необходимо). Кроме того, таким образом браузеры могут отправлять только несколько килобайт. - person Benjamin M; 24.02.2016
comment
@BenjaminM замечает, что политика одинакового происхождения только предотвращает доступ кода javaScript к результату, поэтому, пока запрос заблокирован, он фактически достигает сервера - jsbin.com/mewaxikuqo/edit?html,js,output Я тестировал это только в firefox, но вы можете открыть инструменты разработчика и увидеть, что даже если вы получаете блокировку запроса на кросс-источник удаленный сервер фактически видит весь запрос. вот почему у вас должны быть токены или пользовательские заголовки (и, если возможно, оба) для всех ваших запросов POST. - person Yoni Jah; 19.05.2016
comment
Отличное письмо. Итак, ответ на вопрос - нет, не так ли? - person Qian Chen; 15.10.2016
comment
Да, в основном ответ отрицательный, ЕСЛИ вы делаете это правильно и соблюдаете правила!. Прочтите комментарии и другие ответы здесь! Вы увидите, что есть некоторые подводные камни (например, использование session / localStorage или файлов cookie и т. Д.). Если вы не уверены в этом, вы можете комбинировать CSRF с JWT, в этом нет ничего плохого. - person Benjamin M; 17.10.2016

TL;DR

JWT, если он используется без файлов cookie, устраняет необходимость в токене CSRF - НО! сохраняя JWT в session / localStorage, вы раскрываете свой JWT и личность пользователя, если ваш сайт имеет XSS-уязвимость (довольно часто). Лучше добавить csrfToken ключ к JWT и сохранить JWT в файле cookie с установленными атрибутами secure и http-only.

Прочтите эту статью с хорошим описанием для получения дополнительной информации https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage

Вы можете сделать эту защиту CSRF без сохранения состояния, включив утверждение xsrfToken JWT:

{ "iss": "http://galaxies.com", "exp": 1300819380, "scopes": ["explorer", "solar-harvester", "seller"], "sub": "[email protected]", "xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e" }

Таким образом, вам нужно будет сохранить csrfToken в localStorage / sessionStorage, а также в самом JWT (который хранится в защищенном cookie только для http). Затем для защиты csrf убедитесь, что токен csrf в JWT совпадает с отправленным заголовком csrf-token.

person Scott Jungwirth    schedule 11.05.2016
comment
Мне это кажется наиболее здравым подходом к безопасности, особенно если приложению javascript предоставляется токен обновления. Вы действительно не являетесь злоумышленником для csrf, чтобы иметь возможность подделать метод обновления токена. - person J-DawG; 17.06.2016
comment
Следует ли исключить использование токена csrf во время аутентификации пользователя по API? - person user805981; 07.09.2016
comment
Стоит отметить (как другие также упоминали в комментариях к исходной ссылке), что любое смягчение CSRF, которое использует а) файлы cookie, которые не предназначены только для http, или б) хранит токен CSRF в локальном хранилище, уязвимо для XSS. Это означает, что представленный подход может помочь сохранить секрет JWT от злоумышленника, использующего XSS, но злоумышленник все равно сможет выполнить вредоносный запрос в вашем API, потому что он может предоставить действительный JWT (через файл cookie, спасибо браузеру) и токен CSRF (читается через внедренный JS из локального хранилища / cookie). - person Johannes Rudolph; 27.12.2016
comment
На самом деле даже токен CSRF не может защитить вас на этом уровне XSS, поскольку вы предполагаете, что злоумышленник может получить доступ к localStorage, который в настоящее время единственный способ получить доступ к нему - это иметь доступ на уровне сценария, к которому они в любом случае могут взглянуть на токен CSRF . - person itsnotvalid; 15.01.2017
comment
Разве это не то, что говорил @JohannesRudolph? Как только вы сохраняете токен CSRF в веб-хранилище / cookie, не предназначенном только для http, вы увеличиваете свое влияние на XSS-атаку, потому что они доступны через JS. - person adam-beck; 27.01.2017
comment
Спасибо за комментарии, ребята; Я не хочу создавать впечатление, что это как-то безопасно, даже если на вашем сайте есть XSS-уязвимость. Вы все правы в том, что с токеном CSRF, сохраненным в локальном хранилище, при наличии XSS-уязвимости злоумышленник сможет подделывать запросы. Разница, возможно, незначительна, но в описанном мной методе JWT не может быть украден (безопасный файл cookie только для http) по сравнению с сохранением JWT в локальном хранилище, который может быть украден. - person Scott Jungwirth; 27.01.2017
comment
Здесь не полный эксперт, но если вы все еще сталкиваетесь с XSS, как и вначале, я не уверен, что часть Лучше добавить ... действительно работает. Возможно, злоумышленнику немного сложнее получить токен CSRF, но в конце концов он все еще может выполнить запрос от вашего имени, даже не зная токен JWT. Это верно? Спасибо - person superjos; 01.03.2017
comment
JWT не может быть украден из файла cookie, предназначенного только для http, но токен CSRF может быть украден, так как он нужен где-то для чтения. Если у вас есть ненадежные javascript-файлы на вашей странице, вы все еще уязвимы, но я не знаю, есть ли реальная защита от ненадежных js-файлов, кроме тщательного их избегания. Если вы не используете файлы cookie, вы раскрываете токен аутентификации, а если вы используете, то вы раскрываете свой токен CSRF. Я ошибся? - person Samo; 10.04.2017
comment
Пожалуйста, объясните, почему раскрытие токена CSRF для кражи безопаснее, чем раскрытие JWT для кражи, особенно когда JWT отправляется автоматически? - person java-addict301; 04.03.2019