Как безопасно отправлять пароль через HTTP?

Если на экране входа пользователь отправляет форму со своим именем пользователя и паролем, пароль отправляется простым текстом (даже с POST, исправьте меня, если я ошибаюсь).

Итак, вопрос в том, как правильно защитить пользователя и его пароль от третьей стороны, которая могла бы подслушивать данные связи?

Я знаю, что HTTPS является решением проблемы, но есть ли способ обеспечить по крайней мере некоторый уровень безопасности с использованием стандартного HTTP-протокола (запрос POST)? (возможно, с помощью javascript)

ИЗМЕНИТЬ Возможно, я забыл некоторые важные вещи.

Я был о странице - это страница с PHP, созданная для входа в систему, которая, конечно же, отправляется пользователю в HTTP GET-запросе в виде HTML файла. Соединение между сервером и клиентом не установлено (@Jeremy Powel), поэтому я не могу создать такой протокол установления связи. И я хочу, чтобы весь процесс был прозрачным для пользователя - он хочет отправить пароль, а не заниматься криптографией.

Спасибо.

Ответ 1

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

Ответ 2

Безопасная аутентификация - это широкая тема. В двух словах, как упоминалось в @jeremy-powell, всегда рекомендуется отправлять учетные данные через HTTPS вместо HTTP. Это уберет много головных болей, связанных с безопасностью.

Сертификаты TSL/SSL в наши дни довольно дешевы. На самом деле, если вы не хотите тратить деньги вообще, существует бесплатный letencrypt.org - автоматический центр сертификации.

Вы можете сделать еще один шаг и использовать caddyserver.com, который вызывает letencrypt в фоновом режиме.

Теперь, как только мы спустим HTTPS...

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

  • Имя пользователя и пароль объединяются в строку, разделенную двоеточие, например: имя пользователя: пароль
  • Полученная строка кодируется с использованием вариант RFC2045-MIME Base64, за исключением, не ограничиваясь этим, 76 char/линия.
  • Метод авторизации и пробел, то есть "Базовый", тогда положить перед закодированной строкой.

источник: Википедия: заголовок авторизации

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

Есть несколько веских причин, по которым вы должны использовать заголовок авторизации

  • Это стандартный
  • Это просто (после того, как вы узнаете, как их использовать)
  • Это позволит вам войти на уровень URL, например: https://user:[email protected]/login (например, Chrome автоматически преобразует его в заголовок Authorization)

ВАЖНО:
Как отметил @zaph в своем комментарии ниже, отправка конфиденциальной информации как запроса GET - это не очень хорошая идея, поскольку она, скорее всего, попадет в журналы сервера.

enter image description here

Ответ 3

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

  • Сервер отправляет случайное число, R, клиенту.
  • Клиент отправляет H (R, S) обратно на сервер (где H является криптографической хэш-функцией, например SHA-256)
  • Сервер вычисляет H (R, S) и сравнивает его с ответом клиента. Если они совпадают, сервер знает, что клиент знает пароль.

Edit:

Здесь есть проблема со свежестью R и тем фактом, что HTTP не имеет гражданства. Это может быть вызвано тем, что сервер создает секрет, назовите его Q, что знает только сервер. Затем протокол будет выглядеть следующим образом:

  • Сервер генерирует случайное число R. Затем он отправляет клиенту H (R, Q) (который не может быть подделан клиентом).
  • Клиент отправляет R, H (R, Q) и вычисляет H (R, S) и отправляет все обратно на сервер (где H является криптографической хэш-функцией, например SHA-256).
  • Сервер вычисляет H (R, S) и сравнивает его с ответом клиента. Тогда он принимает R и вычисляет (снова) H (R, Q). Если клиентская версия H (R, Q) и H (R, S) соответствует перерасчету сервера, сервер считает, что клиент аутентифицирован.

Следует отметить, что, поскольку H (R, Q) не может быть подделана клиентом, H (R, Q) действует как файл cookie (и поэтому может быть фактически реализован как файл cookie).

Другое Редактировать:

Предыдущее редактирование протокола неверно, поскольку любой, кто наблюдал H (R, Q), похоже, может воспроизвести его с правильным хешем. Сервер должен помнить, какие R уже не свежие. Я CW'ing этот ответ, поэтому вы, ребята, можете отредактировать это и разработать что-то хорошее.

Ответ 4

Если ваш веб-хостинг позволяет это, или вам нужно будет работать с конфиденциальными данными, тогда используйте HTTPS, точка. (Это часто требуется по закону afaik).

В противном случае, если вы хотите сделать что-то через HTTP. Я бы сделал что-то подобное.

  1. Сервер встраивает свой открытый ключ в страницу входа.
  2. Клиент заполняет форму входа и нажимает кнопку отправить.
  3. AJAX-запрос получает текущую метку времени с сервера.
  4. Сценарий на стороне клиента объединяет учетные данные, временную метку и соль (хешируется из аналоговых данных, например, движений мыши, событий нажатия клавиш), шифрует их с помощью открытого ключа.
  5. Представляет полученный хэш.
  6. Сервер расшифровывает хеш
  7. Проверяет, достаточно ли свежа метка времени (допускает только короткое 5-10 секундное окно). Отклоняет вход в систему, если timestamp слишком старая.
  8. Сохраняет хеш 20 секунд. Отклоняет тот же хэш для входа в систему в течение этого интервала.
  9. Аутентифицирует пользователя.

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

О безопасности токена сессии. Это немного сложнее. Но это может сделать повторное использование украденного токена сессии немного сложнее.

  1. Сервер устанавливает дополнительный сеансовый cookie, который содержит случайную строку.
  2. Браузер отправляет этот файл cookie при следующем запросе.
  3. Сервер проверяет значение в куки, если оно отличается, то уничтожает сеанс, в противном случае все в порядке.
  4. Сервер снова устанавливает cookie с другим текстом.

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

РЕДАКТИРОВАТЬ: Обратите внимание, что это не предотвращает атаки MITM, если злоумышленник создает свою собственную страницу с другим открытым ключом и отправляет запросы прокси на сервер. Для защиты от этого открытый ключ должен быть закреплен в локальном хранилище браузера или в приложении, чтобы обнаруживать подобные уловки.

О реализации: RSA, вероятно, наиболее известный алгоритм, но он довольно медленный для длинных ключей. Я не знаю, насколько бы быстрой была реализация PHP или Javascript. Но, вероятно, есть более быстрые алгоритмы.

Ответ 5

Я бы использовал серверную систему обмена ключами Diffie-Hellman на стороне сервера и на стороне клиента с AJAX или несколькими формами (я рекомендую первый), хотя я не вижу никаких хороших реализаций в Интернете. Помните, что JS-библиотека всегда может быть повреждена или изменена MITM. Локальное хранилище может использоваться для борьбы с этим, в какой-то степени.

Ответ 6

Вы можете использовать SRP для использования защищенных паролей по небезопасному каналу. Преимущество состоит в том, что даже если злоумышленник обнюхивает трафик или компрометирует сервер, они не могут использовать пароли на другом сервере. https://github.com/alax/jsrp - это библиотека javascript, которая поддерживает защищенные пароли через HTTP в браузере или на стороне сервера (через node).

Ответ 7

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

Вот исходный код Java, который использует асимметричный шифр RSA (используемый PGP) для связи: http://www.hushmail.com/services/downloads/

Ответ 8

вы можете использовать ssl для своего хоста, есть бесплатный проект для ssl, например letencrypt https://letsencrypt.org/