Безопасная реализация JWT на одном сайте

#security #web #cookies #jwt #token

#Безопасность #веб #файлы cookie #jwt #токен

Вопрос:

Я много читал о JWT и обнаружил, что их довольно сложно использовать безопасным способом защиты от CSRF и XSS.
Пока я не понял, что мои токены, вероятно, не покинут мой уникальный домен… Это привело меня к этой идее реализации:

  1. Используйте токен обновления вместе с токеном доступа. Таким образом, я могу установить короткое время истечения срока действия токена доступа и ограничить вызовы базы данных для проверки пользователя, и только когда истечет срок действия токена доступа, выполнить простую проверку, запросив у базы данных, что токен обновления не занесен в черный список, прежде чем отправлять новый токен доступа пользователю.
  2. Я понял, что если я сохраню токен в локальном / сеансовом хранилище, он будет уязвим для атак XSS, но если я сохраню его в файле cookie только для HTTP, он будет уязвим для атак CSRF.
  3. Поскольку мне не нужно получать доступ к токену внутри JavaScript и что мне нужен этот токен только на одном веб-сайте, я подумал, что могу сохранить токен доступа внутри HTTP-файла cookie (таким образом, он защищен от XSS) вместе с флагом secure и тем же флагом сайта, установленным на strict(предотвращение CSRF).
  4. И что касается токена обновления, я мог бы сохранить его внутри файла cookie только для HTTP, который имеет тот же безопасный флаг, но на этот раз без того же флага сайта. Поскольку сервер никогда не будет выполнять какие-либо действия только на основе токена обновления, я думаю, что поэтому он не будет подвержен атакам CSRF. Единственное, что сервер будет делать с токеном обновления, это отправлять обратно новый токен доступа, который, если я правильно понял, не может быть прочитан злоумышленником CSRF. Уязвимость CSRF позволяет злоумышленнику сделать запрос к серверу (который автоматически будет содержать файлы cookie только для HTTP), но он не может прочитать ответ на этот запрос.

Я не знаю, будет ли эта реализация JWTs безопасной или я что-то пропустил…

Это то, о чем я спрашиваю вас (JWTs и экспертов по веб-безопасности), будет ли это хорошей реализацией JWTs?

Комментарии:

1. Я думаю, вам просто нужен простой старый идентификатор сеанса с сеансами на стороне сервера. JWT практически не приносит пользы для вашего использования, но сложность не способствует безопасности.

Ответ №1:

Сначала несколько слов о JWTs. Обычный сеанс на стороне сервера старой школы (с длинным случайным идентификатором сеанса, правильно сохраненным в защищенном файле HttpOnly, возможно, также в файле cookie того же сайта) в большинстве случаев «более безопасен», чем любой JWT. Причина в том, что JWT хранят состояние на клиенте, где оно более доступно злоумышленнику, автономные атаки могут выполняться против задействованной криптографии, также JWT являются обычным текстом, и защищена только их целостность (т.Е. они защищены от изменений на стороне клиента, но не от просмотра содержимого по умолчанию, хотя вы могли бы использовать JWE и зашифрованный JWT). И последнее, но не менее важное: реализация более сложная, а простота отлично подходит для безопасности.

Таким образом, вы будете использовать JWT, когда вам нужна выгода, которую он предоставляет.

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

Еще одним преимуществом является то, что вы можете использовать его для нескольких источников. Если вы получаете файл cookie сеанса HttpOnly, который будет управляться браузером, javascript не сможет отправить его другим источникам, например API или чему-то еще — в этом весь смысл, у JS нет доступа. Но иногда это действительно необходимо, особенно в сценариях единого входа, где у вас есть поставщик удостоверений (компонент, обеспечивающий вход в систему) и службы (например. API), на которых вы хотите использовать свой токен доступа. В этом случае классический файл cookie не будет работать, а JWT очень удобны.

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

И тогда, допустим, вы решили использовать JWT, как насчет токенов обновления. Это еще одна обычно неправильно понимаемая особенность аутентификации на основе токенов. Смысл использования токенов обновления заключается в том, чтобы иметь возможность использовать токены доступа с коротким сроком действия, поэтому, если токен доступа будет скомпрометирован, он, по крайней мере, ограничен по времени. Но если вы храните токен обновления так же, как токен доступа, почему злоумышленник не получит его тоже?

Имеет смысл иметь токен обновления только в том случае, если вы храните его по-другому, в противном случае у вас могли бы быть просто долговечные токены доступа, и это не было бы менее безопасным.

Типичной вещью является наличие поставщика удостоверений («сервер входа» или IdP), который устанавливает токен обновления (или просто обычный старый идентификатор сеанса) в файле cookie HttpOnly для источника поставщика удостоверений, поэтому всякий раз, когда клиент делает запрос к IdP, он «просто работает», если ониуже вошли в систему и могут предоставить новый токен доступа без взаимодействия с пользователем. Затем токен доступа сохраняется во что-то вроде localStorage (для источника службы), подверженный XSS, но, по крайней мере, ограниченный по времени. Если у вас нет такого разделения, отдельный токен обновления, вероятно, не имеет особого смысла.

В качестве последнего замечания, все это очень редко следует реализовывать самостоятельно. Любой язык или платформа, которые вы используете, вероятно, уже имеет одну или несколько известных исправных, поддерживаемых реализаций для аутентификации. Вы должны просто использовать их, но, конечно, это все равно стоит понять.

Пожалуйста, обратите внимание, что в любом реальном приложении могут быть тонкости и определенные обстоятельства, которые несколько меняют то, что вы хотите сделать, но вышесказанное является общим способом думать о безопасной аутентификации.

Комментарии:

1. Большое спасибо! Вы правы, я должен использовать сеансы… Меня привлекла сторона JWTs без состояния, но поскольку мне нужна отмена, это того не стоит… Кроме того, вероятно, не так уж много затрат на выполнение запроса к БД по каждому запросу.