Дизайн аутентификации API и возможность взлома - PullRequest
8 голосов
/ 28 октября 2009

Вопрос: легко ли взломать эту технику аутентификации API?

apiKey = "123456789"
apiCallId = "1256341451"
apiSecret = "67d48e91ab2b7471d4be2a8c2e007d13"
sig = md5(apiKey + apiCallId + apiSecret) = 09c297a354219f173bfc49c2e203ce03

, где

  • apiKey: некоторый уникальный идентификатор пользователя
  • apiCallId: уникальное целое число, значение которого должно увеличиваться (например, отметка времени UNIX)
  • apiSecret: строка известна только пользователю, а нам - не передается в URL
  • sig: подпись этого вызова API "unhackable" - хэш MD5

Пример вызова API:

http://api.domain.com/?apiKey=123456789&apiCallId=1256341451&sig=09c297a354219f173bfc49c2e203ce03&param1=x&param2=y

Этот API-интерфейс не требует сеанса и не предназначен для использования третьей стороной от имени пользователя. Вместо этого он должен использоваться самим пользователем.

Мне очень нравится простота этого. Требование, чтобы apiCallId было уникальным и постоянно увеличивалось, означает, что повторное использование sig невозможно, поэтому я чувствую, что это безопасно (защищено от атак воспроизведения), но я не эксперт.

Другие API используют все параметры GET, отсортированные в алфавитном порядке при расчете sig, но я не понимаю, почему это необходимо при включении apiCallId.

Пожалуйста, попробуйте взломать это сейчас, прежде чем оно будет реализовано и выпущено.

Я приветствую любые отзывы, предложения и образование в области безопасности.

Ответы [ 4 ]

13 голосов
/ 28 октября 2009

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

Что-то, что очень похоже на ваш дизайн, и его было бы целесообразно скопировать, это Схема аутентификации запросов веб-сервисов Amazon

В частности, убедитесь, что ваша схема кодирования параметров однозначна и обратима; Amazon облажался в одной точке. Учитесь на своих ошибках. :)

Если говорить криптографически, то, что вы делаете, называется не подписью, а кодом проверки подлинности сообщения (MAC). MAC может быть создан и проверен любым, кто разделяет секретный ключ (термин «подпись» обычно зарезервирован для схем с открытым ключом, таких как DSA или RSA). MD5 (msg || K) является известным и достаточно разумным MAC; Я не уверен, что вы пропустили это случайно или преднамеренно, но метод, который на первый взгляд кажется эквивалентным, MD5 (K || msg), довольно небезопасен, потому что изворот в том, как MD5 (и большинство других хэшей) функции) означают, что если вы знаете H (m), вы можете легко вычислить H (m || m2) для любого m2 - поэтому, если вы используете MD5 (K || param1 = 5), кто-то может снять это с провода и затем создайте MD5 (K || param1 = 5, param2 = 666). (Возможно, это немного более технически, чем вам интересно, но это называется свойство расширения длины ).

Однако, хотя MD5 (K || msg), вероятно, «в порядке», вам лучше использовать что-то вроде HMAC, потому что оно фактически было разработано как MAC. У MD5 много проблем, но ничего не влияет напрямую на его использование в качестве MAC (пока - таким образом MD4 сломался). Поэтому для проверки на будущее (и проверки) используйте HMAC с SHA-1 или SHA-256. Даже если вы не хотите использовать криптографическую библиотеку, HMAC довольно прост, и для SHA-1 и SHA-2 доступны известные значения, поэтому вы можете проверить свой код .

2 голосов
/ 28 октября 2009

Нет. Целостность других параметров (param1 и param2 в вашем примере) не защищена. Злоумышленник может перехватить вызов и изменить его, как ему нравится, прежде чем переадресовать его. apiCallId предотвращает только повторы, но не изменение первого вызова.

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

0 голосов
/ 29 октября 2009

Я бы предложил использовать цифровые подписи в этом случае, так как они более уместны. Цифровой подписи, например, на apikey более чем достаточно. Вам даже не нужен apisecret и его хэш. Вам нужно только убедиться, что цифровая подпись остается конфиденциальной (как хэш md5).

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

Сервер -> API: Nonce (= некоторое случайное число)

API -> Сервер: Enc (nonce + цифровая подпись)

это шифруется открытым ключом сервера, а цифровая подпись размещается с закрытым ключом сервера.

Теперь у вас не может быть повторной атаки. Тем не менее, по-прежнему существует проблема человека в средней атаке, но исправить это не так тривиально (но вполне осуществимо). Таким образом, в зависимости от уровня безопасности, который вы хотите / нуждаетесь, вы можете адаптировать свои технические меры.

0 голосов
/ 28 октября 2009

Хорошо, если бы я знал секрет, тогда я мог бы создать сигнал и передать его. То, что делалось для одного из моих стартапов, - это еще больше повысить параметр sig, заставив sig полагаться на другие параметры, а также на requestID (UUID) и временную метку, и хранить этот UUID (соображения безопасности в течение нескольких часов, чтобы запретить хакеру вызывая одну и ту же функцию снова и снова). Таким образом, вы не можете вызвать тот же вызов снова, вам нужно будет сгенерировать новый UUID, и если хакер заменит UUID в параметре, который sig аннулирует, и он не знает, как сгенерировать sig, потому что, кроме секрета, мы также генерирует подпись на основе внутреннего ключа длиной 30 символов. Так эссенция

MD5 (Алфавитный список параметров + APiKEY + callID + Secert + someLonginternalKey)

не уверен, что я ответил на ваш вопрос, но это еще один способ обеспечения безопасности для API

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...