[Перевод] Рукопожатие SSH простыми словами

Secure Shell (SSH) — широко используемый протокол транспортного уровня для защиты соединений между клиентами и серверами. Это базовый протокол в нашей программе Teleport для защищённого доступа к инфраструктуре. Ниже относительно краткое описание рукопожатия, которое происходит перед установлением безопасного канала между клиентом и сервером и перед началом полного шифрования трафика.

Обмен версиями

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

Обмен ключами

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

Инициализация обмена ключами

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

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

Криптографические примитивы Teleport по умолчанию

Инициализация протокола Диффи — Хеллмана на эллиптических кривых

Поскольку обе стороны используют один и тот же алгоритм для выбора криптографических примитивов из списка поддерживаемых, после инициализации можно немедленно начать обмен ключами. Teleport поддерживает только протокол эллиптических кривых Диффи-Хеллмана (Elliptic Curve Diffie-Hellman, ECDH), так что обмен ключами начинается с того, что клиент генерирует эфемерную пару ключей (закрытый и связанный с ним открытый ключ) и отправляет серверу свой открытый ключ в сообщении SSH_MSG_KEX_ECDH_INIT.

Стоит подчеркнуть, что эта ключевая пара эфемерна: она используется только для обмена ключами, а затем будет удалена. Это чрезвычайно затрудняет проведение класса атак, где злоумышленник пассивно записывает зашифрованный трафик с надеждой украсть закрытый ключ когда-нибудь в будущем (как предусматривает закон Яровой — прим. пер.). Очень трудно украсть то, чего больше не существует. Это свойство называется прямой секретностью (forward secrecy).

[Перевод] Рукопожатие SSH простыми словами 1

Рис. 1. Генерация сообщения инициализации обмена ключами

Ответ по протоколу Диффи — Хеллмана на эллиптических кривых

Сервер ждёт сообщение SSH_MSG_KEX_ECDH_INIT, а при получении генерирует собственную эфемерную пару ключей. С помощью открытого ключа клиента и собственной пары ключей сервер может сгенерировать общий секрет K.

Затем сервер генерирует нечто, называемое хэшем обмена H, и подписывает его, генерируя подписанный хэш HS (подробнее на рис. 3). Хэш обмена и его подпись служат нескольким целям:

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

Хэш обмена генерируется путём взятия хэша (SHA256, SHA384 или SHA512, в зависимости от алгоритма обмена ключами) следующих полей:

  • Мэджики M. Версия клиента, версия сервера, сообщение клиента SSH_MSG_KEXINIT, сообщение сервера SSH_MSG_KEXINIT.
  • Открытый ключ (или сертификат) хоста сервера HPub. Это значение (и соответствующий ему закрытый ключ HPriv) обычно генерируется во время инициализации процесса, а не для каждого рукопожатия.
  • Клиентский открытый ключ А
  • Серверный открытый ключ B
  • Общий секрет K

С этой информацией сервер может сконструировать сообщение SSH_MSG_KEX_ECDH_REPLY, применив эфемерный открытый ключа сервера B, открытый ключ хоста сервера HPub и подпись на хэше обмена HS. См. рис. 4 для более подробной информации.

[Перевод] Рукопожатие SSH простыми словами 2
Рис. 2. Генерация хэша обмена H

Как только клиент получил от сервера SSH_MSG_KEX_ECDH_REPLY, у него есть всё необходимое для вычисления секрета K и хэша обмена H.

В последней части обмена ключами клиент извлекает открытый ключ хоста (или сертификат) из SSH_MSG_KEX_ECDH_REPLY и проверяет подпись хэша обмена HS, подтверждающую право собственности на закрытый ключ хоста. Чтобы предотвратить атаки типа «человек в середине» (MitM), после проверки подписи открытый ключ хоста (или сертификат) проверяется по локальной базе известных хостов; если этот ключ (или сертификат) не является доверенным, соединение разрывается.

The authenticity of host 10.10.10.10 (10.10.10.10)' can't be established.
ECDSA key fingerprint is SHA256:pnPn3SxExHtVGNdzbV0cRzUrtNhqZv+Pwdq/qGQPZO3.
Are you sure you want to continue connecting (yes/no)?

SSH-клиент предлагает добавить ключ хоста в локальную базу известных хостов. Для OpenSSH это обычно ~/.ssh/known_hosts

Такое сообщение означает, что представленного ключа нет в вашей локальной базе данных известных хостов. Хороший способ избежать таких сообщений — использовать вместо ключей сертификаты SSH (что Teleport делает по умолчанию), которые позволяют вам просто хранить сертификат удостоверяющего центра в локальной базе известных хостов, а затем проверять все хосты, подписанные этим УЦ.

[Перевод] Рукопожатие SSH простыми словами 3
Рис. 3. Генерация ответа при обмене ключами ECDH

Новые ключи

Перед тем, как начать массовое шифрование данных, остался последний нюанс. Обе стороны должны создать шесть ключей: два для шифрования, два вектора инициализации (IV) и два для целостности. Вы можете спросить, зачем так много дополнительных ключей? Разве не достаточно общего секрета K? Нет, не достаточно.

Во-первых, почему нужны отдельные ключи для шифрования, целостности и IV. Одна из причин связана с историческим развитием протоколов, таких как TLS и SSH, а именно с согласованием криптографических примитивов. В некоторых выбранных криптографических примитивах повторное использование ключа не представляет проблемы. Но, как верно объясняет Хенрик Хеллстрём, при неправильном выборе примитивов (например, AES-256-CBC для шифрования и и AES-256-CBC-MAC для аутентификации) последствия могут быть катастрофическими. Следует отметить, что разработчики протоколов постепенно отказываются от такой гибкости, чтобы сделать протоколы более простыми и безопасными.

Далее, зачем используются ключи каждого типа.

Ключи шифрования обеспечивают конфиденциальность данных и применяются с симметричным шифром для шифрования и дешифрования сообщения.

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

Следует отметить, что современные шифры AEAD (аутентифицированное шифрование с присоединёнными данными, когда часть сообщения шифруется, часть остаётся открытой, и всё сообщение целиком аутентифицировано) вроде aes128-gcm@openssh.com и chacha20-poly1305@openssh.com фактически не используют производный ключ целостности для MAC, а выполняют аутентификацию внутри своей конструкции.

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

[Перевод] Рукопожатие SSH простыми словами 4
Слева направо. (1) Открытый текст в виде изображения. (2) Криптограмма, полученная шифрованием в режиме ECB. (3) Криптограмма, полученная шифрованием в режиме, отличном от ECB. Изображение представляет собой псевдослучайную последовательность пикселей

Использование (и взлом) векторов IV — интересная тема сама по себе, о которой написал Филиппо Вальсорда.

Наконец, почему ключи идут в парах? Как отметил Томас Порнин, если используется только один ключ целостности, злоумышленник может воспроизвести клиенту отправленную ему запись, и он будет считать её действительной. Со спаренными ключами целостности (у сервера и клиента), клиент выполнит проверку целостности шифротекста и такой трюк не сработает.

Теперь с пониманием того, зачем нужны эти ключи, давайте посмотрим, как они генерируются, согласно RFC:

  • Начальный вектор IV от клиента к серверу: HASH(K || H || «A» || session_id)
  • Начальный вектор IV от сервера к клиенту: HASH(K || H || «B» || session_id)
  • Ключ шифрования от клиента к серверу: HASH(K || H || «C» || session_id)
  • Ключ шифрования от сервера к клиенту: HASH(K || H || «D» || session_id)
  • Ключ контроля целостности от клиента к серверу: HASH(K || H || «E» || session_id)
  • Ключ контроля целостности от сервера к клиенту: HASH(K || H || «F» || session_id)

Здесь используется алгоритм хэширования SHA{256, 384 или 512} в зависимости от алгоритма обмена ключами, а символ || подразумевает конкатенацию, то есть сцепление.

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

[Перевод] Рукопожатие SSH простыми словами 5
Рис. 4:. Генерация начального вектора IV. Генерация для других ключей происходит по той же схеме, если заменить A и B на C, D, E и F, соответственно

Заключение

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

Вот как рукопожатие SSH устанавливает безопасное соединение между клиентами и серверами.

Let’s block ads! (Why?)

Читайте также:

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

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