Использование системы ключей API

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

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

Это разумный способ сделать это? Он открыт для атаки грубой силы, но я думаю, что пока секрет длинный (т.е. uuid), это не должно быть большой проблемой...

Мысль

Любой может отправить другой запрос с тем же временем и хэшем, и он будет принят, ведь он действителен, верно?


person Sam    schedule 09.11.2011    source источник
comment
Я рассматривал это, но мне бы очень хотелось что-то легкое, что не требует и авторизации для каждого клиента (токен доступа)   -  person Sam    schedule 09.11.2011
comment
Он широко открыт для атак MITM — если только вы не используете вызов, чтобы посолить хэш.   -  person symcbean    schedule 09.11.2011
comment
@symcbean Это правда, я думаю, что включение запроса API в хэш сведет на нет это?   -  person Sam    schedule 09.11.2011
comment
@Sam: это решило бы проблему MITM, но (если я правильно вас понял) не обеспечило бы защиту от повторных атак.   -  person symcbean    schedule 09.11.2011


Ответы (3)


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

Server                Client

    ---->challenge --->
    <----response------

Например, вызовом может быть одноразовый номер, предоставленный сервером, а ответом клиента может быть хэш пароля с одноразовым номером.

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

Итак, у вас действительно есть три варианта:

Вариант 1. Притворитесь, что проблемы не существует, и используйте протокол «аутентификации» без сохранения состояния. Это ничем не отличается от использования файла cookie. Nonce + пароль-хэш не более безопасен, чем файл cookie. Файлы cookie могут быть украдены и т. д. и воспроизведены. Вся сеть теперь страдает от этих повторных атак.

Вариант 2. Попробуйте прикрутить протокол аутентификации к методу связи без сохранения состояния. Здесь вы бы попросили клиента отправить вам временную метку UTC вместо одноразового номера. Использование метки времени обеспечивает ограниченную защиту от воспроизведения. Очевидно, что ваши часы не будут синхронизированы с часами клиента, поэтому ваш сервер будет разрешать любую отметку времени в пределах некоторой погрешности, и эта погрешность будет погрешностью воспроизведения протокола аутентификации. Обратите внимание, что это нарушает REST, поскольку сообщение аутентификации не является идемпотентным. Идемпотент подразумевает, что «могут быть успешно воспроизведены злоумышленником».

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

Так что, в конце концов, все зависит от того, насколько вы цените доступ к своим API.

person rsj    schedule 09.11.2011
comment
Чтобы справиться с повторным воспроизведением, может потребоваться, чтобы одноразовый номер был уникальным для каждого пользователя, поскольку и сервер, и клиент (если только несколько клиентов не используют одного и того же пользователя) знают используемый одноразовый номер. - person matthiasmullie; 09.11.2011
comment
Даже если предположить, что злоумышленник может только подслушивать и блокировать или вмешиваться в работу клиента (что я и предполагаю), вы все равно будете помнить все когда-либо использовавшиеся одноразовые номера? Хранить их в базе данных и выполнять массовый поиск каждый раз, когда кто-то пытается аутентифицироваться? - person rsj; 09.11.2011
comment
Если вы также отправляете метку времени с каждым запросом (вместе с хэшем, как исходный вопрос), вы можете просто запретить использование одного и того же одноразового номера в течение разрешенного промежутка времени. Если сохраненный одноразовый номер старше разрешенного timstamp, вы удаляете его из базы данных. Если запрос содержит слишком старую метку времени, запрос все равно не будет принят. - person Anders; 20.07.2012

Для API, которые только извлекают данные (кроме личных данных), а не создают, изменяют или удаляют данные, вариант 1 в этот ответ может быть адекватным. См., например, REST API Bing Maps и веб-сервисы Google Maps Premier (где здесь Google Maps также хеширует URL-адрес с цифровой подписью и специальным ключом, известным только пользователю API, который хотя и обеспечивает защиту от изменения URL-адреса, по-видимому, все же не обеспечивает защиту от повторной атаки).

На самом деле некоторые API, извлекающие данные, не используют ключ API, а ограничивают доступ другими способами (например, API YouTube позволяет извлекать общедоступные данные о видео и каналах пользователей без аутентификации, но ограничивает количество последних Запросы).

Варианты 2 и/или 3 требуются для API, которые делают больше, чем просто извлекают общедоступные данные, например, если они изменяют профили пользователей, публикуют контент или получают доступ к личной информации: см., например, страница аутентификации API данных YouTube, где OAuth упоминается как одна из возможных схем аутентификации.

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

(Это ответ, так как он слишком длинный, чтобы быть комментарием.)

person Peter O.    schedule 09.11.2011
comment
Да, это зависит от общих целей безопасности. Если вы продаете доступ, то, возможно, вы не заботитесь о повторных атаках, но ваши клиенты могут, если они будут платить за каждое использование своего ключа. Это все новые возможности, поскольку не так много API-интерфейсов достаточно популярны/ценны, но как только это произойдет, уже слишком поздно укреплять или защищать протокол, поскольку у вас есть огромная база установленных (сейчас) критически важных приложений, которые не являются безопасными. Результат аналогичен тому, что мы видим сейчас с безопасностью веб-приложений; к тому времени, когда будет достигнуто экономическое обоснование или широко распространенное соглашение о защите протокола, это будет слишком дорого. - person rsj; 10.11.2011

Сервер содержит:

  • имя пользователя
  • хэш пароля

Клиент отправляет:

  • имя пользователя
  • случайная строка
  • хеш (хэш пароля + случайная строка)

Когда клиенты вызывают сервер, сервер создает хэш хэша пароля (который он знает сам) + случайную строку (данную в GET при вызове клиента) и оценивает, соответствует ли она хэшу (данному в GET при вызове клиента)

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

И, очевидно, хорошие алгоритмы хэширования: под вопросом отсутствие rot13 и даже исключительно md5.

person matthiasmullie    schedule 09.11.2011
comment
Даже лучше - нет, это минимум, необходимый для обеспечения безопасности операции, но он все еще открыт для повторных атак. Использование умного хеша не решит эту проблему. - person symcbean; 09.11.2011