Где хранить JWT в браузере? Как защититься от CSRF?

159

Я знаю аутентификацию на основе файлов cookie. SSL и флаг HttpOnly могут применяться для защиты аутентификации на основе файлов cookie от MITM и XSS. Однако для защиты от CSRF потребуются более специальные меры. Они просто немного сложны. ( ссылка )

Недавно я обнаружил, что JSON Web Token (JWT) является довольно популярным решением для аутентификации. Я знаю материалы о кодировании, декодировании и проверке JWT. Тем не менее, я не понимаю, почему некоторые веб-сайты / учебники не говорят о необходимости защиты CSRF, если используется JWT. Я прочитал довольно много и пытаюсь суммировать проблемы ниже. Я просто хочу, чтобы кто-то смог представить общую картину JWT и уточнить концепции, которые я неправильно понял в отношении JWT.

  1. Если JWT хранится в cookie, я думаю, что это то же самое, что и аутентификация на основе cookie, за исключением того, что серверу не нужно иметь сеансы для проверки cookie / токена. По-прежнему существует риск в отношении CSRF, если не будут приняты специальные меры. Разве JWT не хранится в cookie?

  2. Если JWT хранится в localStorage / sessionStorage, то нет cookie, поэтому не нужно защищать от CRSF. Вопрос в том, как отправить JWT на сервер. Я обнаружил, что здесь предлагается использовать jQuery для отправки JWT по HTTP-заголовку ajax-запросов. Таким образом, только запросы ajax могут выполнять аутентификацию?

  3. Кроме того, я нашел еще один блог- шоу, в котором используются «заголовок авторизации» и «носитель» для отправки JWT. Я не понимаю метод, о котором говорит блог. Может ли кто-нибудь объяснить подробнее о «заголовке авторизации» и «предъявителе»? Делает ли это, что JWT передается по HTTP-заголовку ВСЕХ запросов? Если да, то как насчет CSRF?

Timespace7
источник

Ответы:

70

Токены JWT популярны, поскольку они используются в качестве формата токенов по умолчанию в новых протоколах авторизации и аутентификации, таких как OAuth 2.0 и OpenID Connect .

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

Аутентификация на носителе является одной из схем аутентификации, определенных в HTTP. Это в основном означает, что YOUвставьте токен (JWT) в HTTP-заголовок авторизации запроса. Браузер NOTсделает это автоматически, поэтому он не подходит для защиты вашего сайта. Поскольку браузер не добавляет заголовок автоматически в ваш запрос, он не уязвим для атаки CSRF, которая зависит от того, будет ли информация о вашей аутентификации автоматически отправляться в исходный домен.

Схема однонаправленного канала часто используется для защиты веб-API (служб REST), которые используются через вызовы AJAX или от мобильных клиентов.

MvdD
источник
1
@ Timespace7 Нет, токены JWT также часто используются от нативных клиентов. OAuth 2.0 имеет потоки, специально предназначенные для нативных (мобильных) клиентов. Чего они не делают, так это неявной аутентификации браузера (например, куки или обычная аутентификация).
MvdD
5
Я говорю, что если ваш API только получает токен JWT из заголовка Authorization, он не уязвим для CSRF. Любой сайт или API, который получает токен из куки-файла, нуждается в смягчении CSRF.
MvdD
13
Означает ли это, что мы можем эффективно хранить jwt в cookie, и будет безопасно, если мы отправим запросы с ним в заголовке авторизации?
Камеронро
10
@cameronjroe вы можете сохранить его в своих файлах cookie, но только если вы не используете свои файлы cookie для аутентификации (в этом случае вы используете свои заголовки)
Jaakko
1
AJAX звонки также происходят из браузера. Токены JWT в основном используются для проверки подлинности веб-API (обслуживающих данные) и файлов cookie, используемых для проверки подлинности веб-приложений (разметка, изображения, CSS и JavaScript)
MvdD
144

Нам нужно хранить JWT на клиентском компьютере. Если мы сохраним его в LocalStorage / SessionStorage, то он может быть легко захвачен атакой XSS. Если мы храним его в cookie-файлах, то хакер может использовать его (без чтения) в CSRF-атаке, выдавать себя за пользователя, связываться с нашим API и отправлять запросы на выполнение действий или получать информацию от имени пользователя.

Но есть несколько способов обезопасить JWT в файлах cookie, чтобы их нельзя было легко украсть (но есть еще несколько продвинутых методов их кражи). Но если вы хотите положиться на LocalStorage / SessionStorage, то к нему можно получить доступ с помощью простой атаки XSS.

Поэтому для решения проблемы CSRF я использую файлы cookie с двойной передачей в своем приложении.

Метод двойного представления файлов cookie

  1. Сохраните JWT в файле cookie HttpOnly и используйте его в безопасном режиме для передачи по HTTPS.

  2. Большинство атак CSRF имеют различный источник или заголовок реферера с вашим исходным хостом в их запросах. Так что проверьте, есть ли у вас какие-либо из них в шапке, они приходят с вашего домена или нет! Если не отвергнуть их. Если в запросе нет ни источника, ни реферера, тогда не стоит беспокоиться. Вы можете положиться на результаты проверки заголовка X-XSRF-TOKEN, которые я объясню на следующем шаге.

  3. Хотя браузер будет автоматически предоставлять ваши файлы cookie для домена запроса, есть одно полезное ограничение: код JavaScript, который выполняется на веб-сайте, не может читать файлы cookie других веб-сайтов. Мы можем использовать это для создания нашего решения CSRF. Чтобы предотвратить CSRF-атаки, мы должны создать дополнительный читаемый Javascript файл cookie, который называется: XSRF-TOKEN. Этот файл cookie должен быть создан, когда пользователь вошел в систему, и должен содержать случайную неуловимую строку. Мы также сохраняем этот номер в самом JWT как частную претензию. Каждый раз, когда приложение JavaScript хочет сделать запрос, ему нужно будет прочитать этот токен и отправить его в пользовательском HTTP-заголовке. Поскольку эти операции (чтение файла cookie, установка заголовка) могут выполняться только в том же домене приложения JavaScript,

Angular JS делает вашу жизнь проще

К счастью, я использую Angular JS в нашей платформе, а Angular упаковывает подход токена CSRF, делая его проще для реализации. Для каждого запроса, который наше приложение Angular отправляет на сервер, $httpслужба Angular будет выполнять следующие действия автоматически:

  • Найдите файл cookie с именем XSRF-TOKEN в текущем домене.
  • Если этот файл cookie найден, он считывает значение и добавляет его в запрос в виде заголовка X-XSRF-TOKEN.

Таким образом, реализация на стороне клиента обрабатывается для вас автоматически! Нам просто нужно установить cookie с именем XSRF-TOKENв текущем домене на стороне сервера, и когда наш API получил какой-либо вызов от клиента, он должен проверить X-XSRF-TOKENзаголовок и сравнить его с XSRF-TOKENJWT. Если они совпадают, то пользователь реален. В противном случае это поддельный запрос, и вы можете его проигнорировать. Этот метод основан на методе Double Submit Cookie.

предосторожность

На самом деле вы по-прежнему подвержены XSS, просто злоумышленник не может украсть у вас JWT-токен для последующего использования, но он все еще может отправлять запросы от имени ваших пользователей с помощью XSS.

Сохраняете ли вы свой JWT в localStorageили вы храните свой XSRF-токен в не HttpOnly cookie, XSS может легко получить оба этих файла. Даже ваш JWT в файле cookie HttpOnly может быть захвачен расширенной атакой XSS, такой как метод XST .

Таким образом, в дополнение к методу двойной отправки файлов cookie, вы всегда должны следовать передовым методам работы с XSS, включая экранирование содержимого. Это означает удаление любого исполняемого кода, который заставил бы браузер делать то, чего вы не хотите. Как правило, это означает удаление // <![CDATA[тегов и атрибутов HTML, которые вызывают оценку JavaScript.

Узнайте больше здесь:

Иман Седиги
источник
1
@AranDehkharghani да, я думаю, это предотвращает повторную атаку, особенно если вы меняете JWT и истекаете срок действия предыдущего JWT каждый раз, когда он используется API. это означает, что ваш JWT станет как одноразовый пароль (OTP). Вы можете использовать JWT по-разному, в зависимости от того, насколько вы заботитесь о безопасности вашей платформы.
Иман Седиги
7
Как вы упомянули, если веб-сайт уязвим для XSS, то это только вопрос времени, когда пользователь будет эксплуатироваться. Похоже, мы торгуем значительной сложностью для очень небольшого повышения безопасности.
Шуссон
3
@shusson Вы должны позаботиться о атаках XSS и XSRF, чтобы защитить свой JWT. Я не согласен с тем, что вы торгуете значительной сложностью ради очень небольшого повышения безопасности. Если безопасность имеет значение, то вам нужно приложить все усилия, чтобы не иметь уязвимостей XSS. Этот метод предназначен для защиты вашего токена от атак XSRF. но это не значит, что вы можете игнорировать уязвимости XSS.
Иман Седиги
5
@ ImanSedighi Я не совсем понял, храня jwt в cookie, вы добавляете сложность, и теперь вам нужно защищаться от XSRF. Так почему бы просто не использовать локальное хранилище с токенами с коротким сроком службы и сосредоточиться на предотвращении XSS?
Шуссон
2
@ Ройи Намир: Спуфинг от Wireshark не должен вызывать беспокойства, если вы используете SSL-сертификат за 10 долларов! Если безопасность сайта важна, вам следует зашифровать данные и использовать протокол HTTPS.
Иман Седиги
2

Еще один аспект всей проблемы хранения JWT:

  1. JWT никогда не должны храниться в вашем localStorage
  2. На самом деле, они даже не должны храниться в ваших cookie-файлах , если вы не можете реализовать очень строгую защиту CSRF.

Оформить заказ для мотивации

  • JWT как id_token похож на ваши учетные данные пользователя
  • JWT как access_token похож на ваш сеансовый токен

Самый безопасный вариант - в памяти . Проверьте это для глубокого погружения

человек
источник