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

228

Задний план:

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

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

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

Чтобы добраться до вопроса:

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

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

дР.
источник
6
Amazon S3 может включать Content-MD5 как часть строки заголовка, чтобы предотвратить описанную вами атаку MITM.
лаз
8
MD5 - очень слабая хеш-функция, и ее использование не рекомендуется в течение многих лет: en.wikipedia.org/wiki/MD5 . Используйте SHA2 в настоящее время. MD5 - это помада на свинье с кризисом идентичности.
Хенрик
6
Startcom предоставляет бесплатные SSL-сертификаты, которые не генерируют предупреждения о сертификатах в основных браузерах
Платон
5
@SeanKAnderson (rant: я нахожу абсурдным, как люди говорят о 99.99999% s, когда интернет находится в осаде шпионскими агентствами, которые уже в 2008 году автоматизировали МНОГО атак - это такой странный способ справиться с реальной проблемой - «Неееет, проблем не будет; моя бабушка не сможет ее взломать»
Хенрик,
2
@Plato Я бы порекомендовал LetsEncrypt в эти дни бесплатно для SSL-сертификатов
shuttle87

Ответы:

168

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

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

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

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

Для тех, кто заинтересован, я подробно остановился на вопросе о схемах аутентификации HTTP и о том, как они работают .

Les Hazlewood
источник
16
Именно. Единственное, что SSL проверяет в отношении вашего API, - это то, что вызов, с которым он имеет дело, не был испорчен в пути. API до сих пор не знает, кто с ним разговаривает, и должны ли они вообще иметь доступ.
Тим Готье
1
Хороший ответ. Я также рекомендовал бы иметь взгляд на эти превосходные ресурсы .. owasp.org/index.php/Web_Service_Security_Cheat_Sheet и owasp.org/index.php/REST_Security_Cheat_Sheet (ПРОЕКТ)
dodgy_coder
2
Небольшой момент, но использование SSL также имеет дополнительное преимущество, заключающееся в предотвращении подслушивания и атак посредников.
dodgy_coder
@Les Hazlewood Не могли бы вы объяснить, как проверка подлинности HTTP Basic через Https может помочь определить, знает ли сервер, с кем он общается?
Весна
@ Лес Хейзлвуд, вот я и задал вопрос; tnx stackoverflow.com/questions/14043397/…
весна
60

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

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

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

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

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

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

mahemoff
источник
3
Я думаю, вы можете получить сертификат GoDaddy ssl примерно за 30 долларов в год. Я был шокирован, увидев, сколько стоят SSL-сертификаты Verisign (600 долларов в год или что-то, если я правильно помню?) Но вариант GoDaddy вполне выполним.
Брайан Армстронг
19
Если вы не используете взаимную аутентификацию SSL / TLS и сертификат, используемый пользователем / клиентом, является доверенным сервером, то вы не аутентифицировали пользователя на сервере / в приложении. Вам нужно будет сделать что-то еще, чтобы аутентифицировать пользователя на сервере / в приложении.
Пол
5
Райан: SSL-шифрование в наши дни требует довольно малой вычислительной мощности по сравнению с тем, что вы использовали бы для генерации ответа с помощью каркаса веб-приложения, такого как Django или Rails и т. Д.
Кэмерон Уолш,
4
Сертификаты от Startcom бесплатны и широко известны. cacert.org - открытая альтернатива с меньшим признанием
Дима Тиснек
17
Это не относится к вопросу, который касается аутентификации.
Сэм Стейнсби,
8

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

wowest
источник
2
Самозаверяющие сертификаты бесплатны, но для AFAIK вам все равно нужен статический IP.
ДФ.
8
@dF не требуется наличие статического IP-адреса, за исключением определенных требований лицензирования коммерческих платных сертификатов.
Крис Марисик
Если у вас есть контроль над хранилищами сертификатов на обоих концах (клиенты и сервер), это может быть жизнеспособным вариантом, но ... управление и распространение сертификатов, вероятно, намного сложнее в производстве, чем в среде разработки. Обязательно поймите сложности этой альтернативы, прежде чем совершать ее.
Алед
5

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

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

ZaDDaZ
источник
9
Придумать строку, которая будет генерировать тот же хеш md5, что и действительный контент, может быть намного проще, чем следовало бы, но придумать неверную версию допустимого контента, которая хэширует с тем же значением, все еще непозволительно сложно. Вот почему md5 больше не используется для хэшей паролей, но все еще используется для проверки загрузок.
Тим Готье
3

В самом деле, оригинальный S3 аутентификации делает позволяют содержание должно быть подписано, хотя и со слабой 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

djsadinoff
источник
1

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

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

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

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

LiorH
источник