Безопасность схем аутентификации REST

Фон:

Я разрабатываю схему аутентификации для веб-службы REST. Это не "действительно" нужно быть безопасным (это скорее персональный проект), но я хочу сделать его максимально безопасным как упражнение/опыт обучения. Я не хочу использовать SSL, так как я не хочу хлопот и, главным образом, расходов на его настройку.

Эти вопросы SO были особенно полезны, чтобы начать меня:

Я думаю об использовании упрощенной версии аутентификации Amazon S3 (мне нравится OAuth, но это кажется слишком сложным для моих нужд). Я добавляю случайно запрограммированный nonce, предоставленный сервером, для предотвращения повторных атак.

Чтобы перейти к вопросу:

Оба S3 и OAuth полагаются на подписание URL-адреса запроса вместе с несколькими выбранными заголовками. Ни один из них не подписывает тело запроса для запросов POST или PUT. Разве это не уязвимо для атаки "человек-в-середине", которая сохраняет URL-адрес и заголовки и заменяет тело запроса любыми данными, которые хочет получить злоумышленник?

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

Ответ 1

Предыдущий ответ касался только SSL в контексте передачи данных и фактически не охватывал аутентификацию.

Вы действительно спрашиваете о надежной аутентификации клиентов REST API. Если вы не используете аутентификацию клиента TLS, только SSL не является жизнеспособным механизмом аутентификации для REST API. SSL без аутентификации клиента аутентифицирует только сервер, что не имеет отношения к большинству API REST, потому что вы действительно хотите аутентифицировать клиента.

Если вы не используете аутентификацию клиента TLS, вам нужно будет использовать что-то вроде схемы аутентификации на основе дайджеста (например, пользовательской схемы Amazon Web Service) или OAuth 1.0a или даже обычной проверки подлинности HTTP (но только через SSL).

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

Для тех, кого это интересует, я расширил SO-вопрос о схемах HTTP-аутентификации и о том, как они работают.

Ответ 2

REST означает работу со стандартами Интернета, а стандартом для "безопасной" передачи в Интернете является SSL. Все остальное будет напуганным и потребует дополнительных усилий по развертыванию для клиентов, которым необходимо будет иметь библиотеки шифрования.

Как только вы зафиксируете SSL, в принципе нет необходимости в аутентификации. Вы можете снова пойти с веб-стандартами и использовать HTTP Basic auth (имя пользователя и секретный токен, отправленный вместе с каждым запросом), поскольку он намного проще, чем сложный протокол подписания и все еще эффективен в контексте безопасного соединения. Вам просто нужно быть уверенным, что пароль никогда не проходит через обычный текст; поэтому, если пароль когда-либо был получен по простому текстовому соединению, вы даже можете отключить пароль и отправить сообщение разработчику. Вы также должны убедиться, что учетные данные не регистрируются в любом месте после получения, так же, как вы не регистрируете обычный пароль.

HTTP Digest - более безопасный подход, поскольку он предотвращает передачу секретного токена; вместо этого это хэш, который сервер может проверить на другом конце. Хотя это может быть излишним для менее чувствительных приложений, если вы приняли меры предосторожности, упомянутые выше. В конце концов, пароль пользователя уже передается в текстовом формате при входе в систему (если только вы не выполняете какое-то причудливое шифрование JavaScript в браузере), а также их файлы cookie для каждого запроса.

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

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

(Обновлено, чтобы освещать последствия подключения только SSL-соединения.)

Ответ 3

Или вы можете использовать известное решение этой проблемы и использовать SSL. Самоподписанные сертификаты бесплатны и личный проект?

Ответ 4

Если вам нужен хэш тела как один из параметров в URL-адресе, и этот URL-адрес подписан через закрытый ключ, тогда атака "человек в середине" сможет заменить тело только тем, что будет генерировать один и тот же хеш. Легко сделать с хеш-значениями MD5, по крайней мере, и когда SHA-1 сломан, ну, вы получите изображение.

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

Ответ 5

Фактически, исходный S3 auth позволяет подписывать контент, хотя и со слабой подписью MD5. Вы можете просто применить свою факультативную практику включения заголовка Content-MD5 в HMAC (строка, которая должна быть подписана).

http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html

Их новая схема аутентификации v4 более безопасна.

http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html

Ответ 6

Помните, что ваши предложения затрудняют общение клиентов с сервером. Им нужно понять ваше инновационное решение и зашифровать данные соответственно, эта модель не так хороша для публичного API (если вы не amazon\yahoo\google..).

В любом случае, если вы должны зашифровать содержимое тела, я предлагаю вам проверить существующие стандарты и решения, например:

XML-шифрование (стандарт W3C)

Безопасность XML