Как стать автором
Обновить

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

Уровень сложностиПростой
Время на прочтение4 мин
Количество просмотров3.6K

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

Суть дилеммы состоит в непонимании работы сертификации серверов и защищённых сетей как со стороны преподавателей, так и с моей стороны. Ведь, создавая сайты, я по стандарту устанавливаю 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 аутентификацию, которая предотвращает доступ злоумышленникам, даже если те получили исходный пароль.

Теги:
Хабы:
Всего голосов 9: ↑5 и ↓4+3
Комментарии19

Публикации