Подпись HTTP-запроса без сеанса - PullRequest
5 голосов
/ 22 декабря 2010

Я имею в виду веб-сервис отдыха, который гарантирует, что для каждого отправленного ему запроса:

  • Запрос сгенерирован пользователем, который его запрашивает;
  • Запрос не был изменен кем-либо еще (uri / method / content / date);
  • Для запросов GET должна быть возможность генерировать URI с достаточным количеством информации для проверки подписи и установки даты истечения срока действия. Таким образом, пользователь может делегировать временные разрешения READ для соавтора на ограниченный период времени на ресурс с сгенерированным URI.

Клиенты проходят проверку подлинности с использованием идентификатора и подписи содержимого на основе своего пароля.

Не должно быть никакого сеанса вообще, и поэтому состояние сервера! Сервер и клиент совместно используют секретный ключ (пароль)

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

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

Служба использует собственный заголовок «Content-signature» для хранения учетных данных. Аутентифицированный запрос должен содержать этот заголовок:

Content-signature: <METHOD>-<USERID>-<SIGNATURE>

<METHOD> is the sign method used, in our case SRAS.
<USERID> stands for the user ID mentioned earlier.
<SIGNATURE> = SHA2(SHA2(<PASSWORD>):SHA2(<REQUEST_HASH>));
<REQUEST_HASH> = <HTTP_METHOD>\n
                 <HTTP_URI>\n
                 <REQUEST_DATE>\n
                 <BODY_CONTENT>;

Запрос считается недействительным через 10 минут после его создания.

Например, типичный запрос HTTP будет:

POST /ressource HTTP/1.1
Host: www.elphia.fr
Date: Sun, 06 Nov 1994 08:49:37 GMT
Content-signature: SRAS-62ABCD651FD52614BC42FD-760FA9826BC654BC42FD

{ test: "yes" }

Сервер ответит:

401 Unauthorized

OR

200 OK

Переменные будут:

<USERID> = 62ABCD651FD52614BC42FD
<REQUEST_HASH> = POST\n
                 /ressource\n
                 Sun, 06 Nov 1994 08:49:37 GMT\n
                 { test: "yes" }\n

Параметры URI

Некоторые параметры могут быть добавлены в URI (они перегружают информацию заголовков):

  • _sras.content-signature = - - : ЗАДАТЬ учетные данные в URI, а не в заголовок HTTP. Это позволяет пользователю поделиться подписанным запросом;
  • _sras.date = вс, 6 ноября 1994 г. 08:49:37 GMT (дата запроса *): дата создания запроса.
  • _sras.expires = Sun, 06 ноября 1994 08:49:37 GMT (дата истечения срока действия *): сообщить серверу, что срок действия запроса не должен истечь раньше указанной даты

* формат даты: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.18

Спасибо за ваши комментарии.

Ответы [ 2 ]

5 голосов
/ 26 декабря 2010

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

1- Обычно добавляется префикс "X-Namespace-" к нестандартным заголовкам, в вашем случае вы можете назвать свой заголовок примерно так:"X-SRAS-Content-Signature".

2 - заголовок Date может не обеспечивать достаточного разрешения для значения nonce, поэтому я бы посоветовал использовать метку времени с разрешением не менее 1 миллисекунды.

3- Если вы не сохраните хотя бы последний одноразовый номер, можно все равно воспроизвести сообщение в 10-минутном окне, что, вероятно, недопустимо для запроса POST (может создать несколько экземпляров с одинаковыми значениями в веб-службе REST).Это не должно быть проблемой для команд GET PUT или DELETE.

Однако в PUT это можно использовать для атаки типа «отказ в обслуживании», заставляя многократно обновлять один и тот же объект в предлагаемом 10-минутном окне.,В GET или DELETE существует похожая проблема.

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

4- Этот метод также требует, чтобы клиент и серверы были синхронизированы по часам с перекосом менее 10 минут.Это может быть сложно для отладки или невозможно применить, если у вас есть клиенты AJAX, для которых вы не контролируете часы.Для этого также необходимо установить все временные метки в UTC.

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

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

5 - Необходимо также обратить внимание на повторные передачи из-за сетевых ошибок.Вы не можете предполагать, что сервер не получил последнее сообщение, для которого TCP-подтверждение не было получено клиентом до разрыва TCP-соединения.Поэтому одноразовый номер необходимо увеличивать между каждой повторной передачей выше уровня TCP и пересчетом сигнатуры с новым одноразовым номером.Тем не менее, необходимо добавить номер сообщения для предотвращения двойного выполнения на сервере: двойной POST приведет к созданию объекта 2.

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

7 - Ваш метод не гарантирует клиенту подлинность сервера и отсутствие перехвата DNS.Проверка подлинности сервера обычно считается важной для безопасной связи.Эта услуга может быть предоставлена ​​путем подписания ответов от сервера, используя тот же одноразовый номер, что и для запроса.

1 голос
/ 26 декабря 2010

Я хотел бы отметить, что вы можете выполнить это с помощью OAuth, в первую очередь "2-legged OAuth", где клиент и сервер совместно используют секрет.См. http://tools.ietf.org/html/rfc5849#page-14. В вашем случае вы хотите опустить параметр oauth_token и, возможно, использовать метод подписи HMAC-SHA1.В этом нет ничего особенно болтливого;вам не нужно проходить через потоки получения токенов OAuth, чтобы делать это таким образом.Преимущество этого заключается в возможности использования любой из нескольких существующих библиотек OAuth с открытым исходным кодом.

Что касается состояния на стороне сервера, вам необходимо отслеживать, какие секреты хранятся у каких клиентов, а также у каких.В последнее время использовались одноразовые номера (для предотвращения повторных атак).Вы можете пропустить одноразовые проверки / время жизни, если вы запускаете вещи по HTTPS, но если вы собираетесь это сделать, тогда HTTPS + Basic Auth даст вам все, что вы описали, без необходимости писать новое программное обеспечение.

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