Подтвердить что ты не робот

Реализация маркера аутентификации веб-службы REST

Я реализую веб-службу REST с использованием С#, которая будет размещаться на Azure в качестве облачного сервиса. Поскольку это служба REST, она не имеет состояния и, следовательно, не содержит cookie или сеанса.

Доступ к веб-сервису возможен только через HTTPS (сертификат, предоставляемый StartSSL.com).

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

Токен будет содержать отметку времени, идентификатор пользователя и IP-адрес клиента.

Все общение будет происходить только через HTTPS, поэтому меня не волнует, что токен перехватывается и используется при повторных атаках; в любом случае токен будет истекать.

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

Мне интересно, как лучше всего защитить содержимое токена, а также проверить, что он не был изменен.

Я планирую сделать следующее, чтобы защитить токен:

Клиент успешно выполняет вход в службу, и служба выполняет:

  • Создайте случайное значение и хэш его с SHA256 1000 раз.
  • Генерировать одноразовый ключ сеанса из личного ключа + хешированное случайное значение.
  • Хешируйте сеансовый ключ с SHA256 1000 раз, а затем используйте его для шифрования токена
  • Используйте закрытый ключ для подписывания зашифрованного токена с помощью RSA.
  • Отправляет зашифрованный токен + подпись + хешированное случайное значение клиенту в незашифрованном пакете JSON.

Когда клиент вызывает службу, он отправляет зашифрованный токен и подпись в незашифрованном пакете JSON для этой службы. Служба будет

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

Я ничего не знаю о шифровании, поэтому у меня есть несколько вопросов:

  • Достаточно ли это или это слишком много?
  • Я прочитал, что для обнаружения фальсификации я должен включить HMAC с токеном. Поскольку я подписываюсь с закрытым ключом, мне все еще нужен HMAC?
  • Должен ли я использовать Rijndael вместо RSA?
  • Если Rijndael является предпочтительным, генерируется ли IV для дешифрования? то есть я могу выбросить его или мне нужно отправить его зашифрованный токен? например Шифрованный токен + HMAC + IV + хешировал случайное значение.

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

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

Спасибо за помощь

4b9b3361

Ответ 1

Ты действительно слишком задумываешься. По правде говоря, лучшая безопасность маркера зависит от случайности или, что более точно, непредсказуемости. Лучшие жетоны абсолютно случайны. Вы правы в том, что проблема заключается в том, что пользователь будет изменять свой токен и использовать его для доступа к учетным записям других пользователей. Это обычная атака, известная как "кража сеанса". Эта атака почти невозможна, когда токены генерируются случайным образом и истекли на стороне сервера. Использование пользовательской информации, такой как IP и/или временная метка, является плохой практикой, поскольку она улучшает предсказуемость. Я сделал атаку в колледже, который успешно угадал активные токены, которые были основаны на отметках времени сервера в микросекундах. Автор приложения подумал, что микросекунды будут меняться достаточно быстро, чтобы они были непредсказуемыми, но это было не так.

Вы должны знать, что, когда пользователи находятся за прокси-серверами, прокси иногда просматривает свои запросы SSL в виде простого текста (по соображениям безопасности многие прокси будут выполнять глубокую проверку пакетов). По этой причине хорошо, что вы заканчиваете сеансы. Если бы ваши пользователи не были уязвимы для таких атак, а также возможных XSS и CSRF.

RSA или Rijndael должны быть достаточными, при условии разумной длины ключа. Кроме того, вы должны использовать HMAC с токеном, чтобы предотвратить вмешательство, даже если вы его подписываете. Теоретически это было бы излишним, поскольку вы подписываетесь с закрытым ключом. Тем не менее, HMAC очень хорошо протестирован, и ваша реализация механизма подписания может быть испорчена. По этой причине лучше использовать HMAC. Вы были бы удивлены тем, как много "сворачивать ваши собственные" реализации безопасности имеют недостатки, которые приводят их к компрометации.

Ты хорошо разбираешься в безопасности. Продолжайте хорошую работу! В этом мире нам нужны более безопасные разработчики.

EDIT:

Считается безопасным включать временные метки/идентификаторы пользователей в токен, если они зашифрованы сильным симметричным секретным ключом (например, AES, Blowfish и т.д.), который имеет только сервер, и пока токен включает в себя тампер -защищенный хэш с ним, такой как HMAC, который зашифрован секретным ключом вместе с идентификатором пользователя/меткой времени. Хэш гарантирует целостность, а шифрование гарантирует конфиденциальность.

Если вы не включаете HMAC (или другой хеш) в шифрование, тогда пользователи могут вмешиваться в зашифрованный токен и расшифровывать его на что-то действительное. Я сделал атаку на сервере, в котором идентификатор пользователя и отметка времени были зашифрованы и использовались в качестве токена без хэша. Изменяя один случайный символ в строке, я смог изменить свой идентификатор пользователя от чего-то вроде 58762 до 58531. Хотя я не мог выбрать "новый" идентификатор пользователя, я смог получить доступ к чужой учетной записи (это было в академических кругах, как часть курса).

Альтернативой этому является использование полностью случайного значения токена и сопоставление его на стороне сервера с сохраненной меткой идентификатора пользователя/времени (которая остается на стороне сервера и, следовательно, вне контроля клиентов). Это требует немного больше памяти и вычислительной мощности, но более безопасно. Это решение, которое вам нужно будет сделать в каждом конкретном случае.

Что касается повторного использования/вывода ключей из IV и других ключей, это обычно нормально, при условии, что ключи действительны только в течение короткого периода времени. Математически маловероятно, что кто-то может их разбить. Однако это возможно. Если вы хотите пройти параноидальный маршрут (что я обычно делаю), генерируйте все новые ключи случайным образом.