Передача пароля по интернету: что безопаснее — хэширование или TLS?

от автора

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

Суть дилеммы состоит в непонимании работы сертификации серверов и защищённых сетей как со стороны преподавателей, так и с моей стороны. Ведь, создавая сайты, я по стандарту устанавливаю SSL-сертификаты к доменам, настраиваю их автопродление, переадресацию с HTTP на HTTPS и забываю о них. Моей основной задачей становится написание сервера с защитой от разного рода уязвимостей.

Согласно логике преподавателей, мой проект на клиентской части должен хэшировать пароль и передавать его на сервер, где он будет сравниваться с уже хранимым хэшем. Однако возникает очевидный вопрос: «А почему злоумышленник не может перехватить хэш и использовать его для аутентификации?» Преподаватели не смогли дать внятного ответа, утверждая, что так «безопаснее». На самом деле такая схема противоречит самой концепции безопасности: читабельный пароль просто заменяется на хэш, который становится уязвимым к атаке Pass-the-Hash. Я же настаивал на важности SSL-сертификатов и использования TLS-протоколов.

Как работает криптография в интернете?

Многие замечали, что браузеры иногда предупреждают о небезопасном подключении к сайтам с HTTPS.

Сайт ФСТЭК, с сертификатом которому не доверяет браузер

Сайт ФСТЭК, с сертификатом которому не доверяет браузер

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

Что такое SSL-сертификат и зачем нужен HTTPS?

Буква «S» в «HTTPS» означает, что сайт использует SSL-сертификат. Сертификат содержит:

  • Приватный и публичный ключи;

  • Дату выдачи и срок действия;

  • Кому и кем он был выдан.

Сертификат сайта ФСТЭК

Сертификат сайта ФСТЭК

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

  • Публичный ключ (его можно показывать всем);

  • Приватный ключ (хранится в секрете).

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

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

Алгоритм Диффи — Хеллмана: объяснение на примере красок

Далее в ход вступает алгоритм Диффи — Хеллмана. Он позволяет двум сторонам создать общий секретный ключ даже в присутствии наблюдателя.

алгоритм Диффи — Хеллмана на примере красок

алгоритм Диффи — Хеллмана на примере красок

Как это работает?

  1. Клиент и сервер договариваются об общем «цвете» (публичном числе).

  2. Каждая сторона добавляет свой секретный «цвет» (секретное число) и отправляет модифицированное значение.

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

MITM-атака и защита от неё

Одним из главных рисков при передаче данных является атака «человек посередине» (MITM). В такой атаке злоумышленник подменяет публичный ключ сервера своим и перехватывает зашифрованные данные.

Как защищает TLS:

  • Использование сертификатов от доверенных центров сертификации (CA) предотвращает подмену ключей.

  • Протокол HSTS (HTTP Strict Transport Security) запрещает использование HTTP, принудительно активируя HTTPS.

  • Современные браузеры проверяют цифровую подпись сертификата и предупреждают пользователя о проблемах безопасности.

Проверяем безопасность соединения с помощью Wireshark

Чтобы убедиться, что данные передаются в зашифрованном виде, я использовал Wireshark.

Для фильтрации нужных пакетов: ip.host == 81.90.182.13, где 81.90.182.13 — это IP-адрес сервера моего проекта.

пакеты, при отправке одного post запроса на сервер

пакеты, при отправке одного post запроса на сервер

На скриншоте можно увидеть несколько строк с информацией о соединении:

  • «Client Hello» – инициация TLS-соединения;

  • «Server Hello» – подтверждение сервером и выбор алгоритма шифрования;

  • «Change Cipher Spec» – обмен сессионными ключами;

  • «Application Data» – зашифрованные GET- и POST-запросы.

GET данные:

зашифрованные GET данные

зашифрованные GET данные
зашифрованные POST данные

зашифрованные POST данные

Из данных скриншотов видно, что отправленные клиентом данные являются полностью зашифрованными. Для наглядности, можно так-же посмотреть на незашифрованный пакет данных, который я отправлял, тестируя работу TCP протокола в C#.

Не зашифрованные данные:

данные без шифрования

данные без шифрования

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

Почему клиентское хэширование – плохая идея?

Хэширование паролей на клиенте не защищает от атак Pass-the-Hash, при которых злоумышленник перехватывает передаваемый хэш и использует его для входа. В отличие от пароля, сервер не отличает скомпрометированный хэш от оригинального.

Простой подход:

  1. Пароль передаётся в зашифрованном виде через HTTPS.

  2. Сервер хэширует его с солью (bcrypt, Argon2, PBKDF2).

  3. Хранимые хэши невозможно использовать напрямую для аутентификации.

Ситуация: злоумышленник симулирует передачу данных

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

Ситуация: злоумышленник получил ключ шифрования

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

Пример механизма защиты с солью:

  1. Сервер отправляет пользователю случайную соль перед аутентификацией.

  2. Пользователь хэширует свой пароль, как это делает сервер.

  3. Затем он добавляет полученную соль к хэшу и снова хэширует.

  4. Отправляет полученное значение на сервер.

  5. Сервер выполняет ту же операцию со своим хранимым хэшем и сравнивает результаты.

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

Итог

Как видно, передача пароля через HTTPS действительно безопасна, так как данные шифруются и недоступны для перехвата.

В отличие от клиентского хэширования, которое не защищает от атаки «Pass-the-Hash», SSL/TLS обеспечивает: Конфиденциальность (перехваченные данные бесполезны без ключа); Целостность (защита от подмены данных); Аутентификацию (проверка подлинности сервера).

Если проект требует безопасной передачи пароля, не нужно хэшировать его на клиенте – используйте SSL/TLS, шифруйте данные и храните пароли с хэшированием уже на сервере.

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


ссылка на оригинал статьи https://habr.com/ru/articles/895968/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *