- PVSM.RU - https://www.pvsm.ru -
SSH — очень мощный и гибкий инструмент, но, как показывает практика, не все понимают, как он работает и правильно его используют. Слово Secure входит в аббревиатуру SSH и является одним из ключевых аспектов протокола, но, часто именно безопасности уделяется недостаточное внимание. В этой статье я хочу рассказать о нескольких типичных ошибках при работе с SSH, а также, о моментах, о которых часто забывают.

Существует несколько способов аутентификации пользователя:
SSH использует ассиметричное шифрование, суть которого заключается в том, что есть два ключа открытый и закрытый. Зашифровать сообщение можно открытым ключом, а расшифровать закрытым. Закрытый ключ хранится в сохранности, а публичный доступен всем. Кроме того, подписать сообщение можно закрытым ключом, а проверить эту подпись — открытым.
На схеме видно, что после обмена публичными ключами два узла могут безопасно общаться между собой через небезопасный Интернет.
Кроме того, аутентификация пользователя может производиться при помощи этой самой пары ключей.
Публичный ключ пользователя необходимо добавить в файл $HOME/.ssh/authorized_keys
В этом файле может быть несколько публичных ключей — все они будут работать.

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

Суть защиты заключается в том, что каждая сторона должна убедиться, что с другой стороны находится именно тот, кто ожидается, а не злоумышленник.
За MITM-защиту на стороне клиента (т.е. за то, чтобы определить, что ты подключаешься именно к своему серверу) отвечает параметр StrictHostKeyChecking и файл known_hosts
Публичные ключи серверов хранятся в файлах
$HOME/.ssh/known_hosts — пользовательский файл
/etc/ssh/ssh_known_hosts— системный файл
Каждая запись в known_hosts является строкой, содержащую поля и использующую пробел в качестве разделителя:
Именно здесь происходит «идентификация» сервера
StrictHostKeyChecking=no|ask|yes
Значения могут быть следующие:
Что нам это дает:
Если со вторым пунктом все понятно, то как быть с первым?
Тут можно выделить как минимум три варианта:

Использование визуализации открытого ключа

Если открытый ключ изменился
Сообщение о смене ключа может происходить по нескольким причинам:
Из моей практики 1 и 2 варианты в сумме стремятся к 100%, но и пункт 3 нельзя исключать тоже
Вот пример лайфхака, который объединяет в себе веб- и ssh-подходы
curl https://server.com/ssh_fingerprint | tee -a ~/.ssh/known_hosts
На первый взгляд это не очень безопасно, однако, эту информацию можно получить при помощи команды
ssh-keyscan example.com
Однако, в первом варианте мы дополнительно проверяем подлинность полученного ключа при помощи HTTPS
В критически важных CI/CD использование комбинации
ssh-keyscan example.com >> ~/.ssh/known_hosts
Во время инициализации совместно с
StrictHostKeyChecking=yes
Позволит надежно защититься от MITM-атак
Часто можно встретить такую картину:

Для каждого сервера на клиенте сгенерированы свои пары ключей и в $HOME/.ssh/ творится полнейший беспорядок.
С одной стороны это безопаснее, нежели, использование одной пары клиентских ключей — при компрометации одного ключа становится скомпрометирована только одна система, а не все, с которыми работал пользователь.
Однако, как показывает практика, этим руководствуются пользователи в последнюю очередь, зачастую они просто выполняют все инструкции по шагам:
ssh-keygen
...
...
Иногда я наблюдал ситуацию, когда одни ключи перетирались другими без какой либо мысли в голове.

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

Расценивайте свой приватный SSH-ключ как ключ от квартиры, где деньги лежат. Более беспечного отношения, чем к SSH-ключам я не видел. Если серьезность сохранения паролей пользователи еще более или менее понимают, то о том, что никому нельзя давать доступ к приватному ключу задумываются единицы.
Что тут можно выделить:
Изменить или добавить пароль можно при помощи команды
ssh-keygen -p
Но часто бывает такая ситуация, когда необходимо со своим ключем перейти на сервер и там уже им воспользоваться. Существует три решения данной задачи:
Из моей практики пользователи в 90% случаев выбирают первые два варианта, а как мы уже говорили: нет ничего более страшного, чем компрометация ключа.
Я же рекомендую воспользоваться третьим способом

SSH-agent хранит секретные ключи и, когда нужно, пользуется ими. Программа (например, ssh), когда ей понадобится воспользоваться секретным ключом, не делает этого сама, а обращается к ssh-agent 'у, который в свою очередь уже сам пользуется известными только ему данными о секретных ключах. Таким образом, секретные ключи не разглашаются никому, даже программам принадлежащим самому пользователю.
Команда ssh-agent создает файл-сокет с именем /tmp/ssh-XXXXXXXX/agent.ppid, через который осуществляется взаимодействие с агентом. Всем дочерним процессам агент при помощи переменных окружения SSH_AUTH_SOCK (в которой хранится имя файла-сокета) и SSH_AGENT_PID (в которой хранится идентификатор процесс агента) сообщает информацию о том, как с ним можно связаться.
Агент выдает информацию в виде, удобном для использования командным интерпретатором.
SSH_AUTH_SOCK=/tmp/ssh-XXt4pHNr/agent.5087; export SSH_AUTH_SOCK;
SSH_AGENT_PID=5088; export SSH_AGENT_PID;
echo Agent pid 5088;
При указании ключа -c агент использует синтаксис C Shell. По умолчанию (и при явном указании ключа -s) используется синтаксис Bourne Shell. Эти переменные следует установить в текущем командном интерпретаторе, поэтому обычно вызов ssh-agent комбинируется с командой eval.
$ eval `ssh-agent`
Agent pid 5088
Агент работает до тех пор, пока не будет явно завершен сигналом либо вызовом
$ ssh-agent -k
Список известных агенту секретных ключей можно посмотреть той же командой ssh-add с ключом командной строки -l. Команда сообщит и отпечаток для каждого ключа.
$ ssh-add -l
1024 46:88:64:82:a7:f9:aa:ea:3b:21:9e:aa:75:be:35:80 /home/user/.ssh/id_rsa (RSA)
Пример работы с ssh-agent можно увидеть ниже

Кроме того, агент решает еще одну задачу: если вы зашифровали приватный ключ, то при обращении к нему каждый раз не будет запрашиваться пароль. Если же использовать агента, то пароль будет необходимо будет вводить только при добавлении ключа в агента.
Если бы каждый раз, когда я наблюдал за набором строки вида
ssh -p 2022 user@server.com -o StrictHostKeyChecking=yes -i ~/.ssh/server.pem
мне давали рубль, то я бы уже давно жил в Сочи.
На локальной машине можно найти файл $HOME/.ssh/config
Host server
User root
HostName 192.168.0.3
IdentityFile ~/.ssh/server.pem
Host example.com
User admin
IdentityFile ~/.ssh/production.pem
Соответственно, можно прописать большинство параметров для хоста в этот файл и не вводить каждый раз.
1. При использовании аутентификации по ключу не забывайте, что остается еще пароль и как бы вы ни защищали свой приватный ключ, злоумышленник сможет подобрать ваш пароль qwerty и войти в систему без необходимости похищать ключ
Можно выделить несколько решений:
PasswordAuthentication no в /etc/ssh/sshd_config
2. Еще можно запретить использование ssh v1
Protocol 2 в /etc/ssh/sshd_config
3. И обязательно закрывать на фаерволе доступ к SSH для ненадежных источников
4. Раньше бы я посоветовал сменить порт со стандартного 22 на другой, но наблюдая за тем, сколько бывает попыток авторизоваться на нестандартных портах я могу сказать однозначно: это не является защитой от взлома.
5. Если уже рассматривать подбор пароля, то не лишним будет настроить fail2ban для того, чтобы ограничить попытки подбора пароля.
6. В протоколе и библиотеках периодически находят проблемы и уязвимости, поэму тут работает универсальный подход — следите за обновлениям ПО и старайтесь регулярно устанавливать как минимум заплатки безопасности.
Читайте документацию, в ней все написано, как бы это пошло не звучало.
SSH очень безопасный протокол, но, зачастую, именно человеческий фактор является основным источником проблем — следите за безопасностью.
Использованные материалы
Защита с помощью SSH ключей
Управление ключами SSH с помощью агента [1]
Автор: Роман Кудлай
Источник [2]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/informatsionnaya-bezopasnost/283616
Ссылки в тексте:
[1] Управление ключами SSH с помощью агента: http://xgu.ru/wiki/%D0%A3%D0%BF%D1%80%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BA%D0%BB%D1%8E%D1%87%D0%B0%D0%BC%D0%B8_SSH_%D1%81_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_%D0%B0%D0%B3%D0%B5%D0%BD%D1%82%D0%B0
[2] Источник: https://habr.com/post/358800/?utm_source=habrahabr&utm_medium=rss&utm_campaign=358800
Нажмите здесь для печати.