В марте 2023 года на популярном сайте для хостинга кода Github случился инцидент с утечкой секретного ключа RSA SSH, который использовался для операций на хосте github.com.

Такие инциденты — совсем не редкость. Чаще всего они квалифицируются как «человеческая ошибка», то есть недосмотр какого-то конкретного сотрудника, который случайно выложил секретные данные в открытый доступ. В данном случае сотрудник случайно закоммитил секретный ключ в открытый репозиторий.

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

Что случилось на Github


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

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
SHA256:uNiVztksCsDhcc0u9e8BujQXVUpKZIDTMczCvj3tD2s.
Please contact your system administrator.
Add correct host key in ~/.ssh/known_hosts to get rid of this message.
Host key for github.com has changed and you have requested strict checking.
Host key verification failed.

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

$ ssh-keygen -R github.com

Или вручную обновить файл ~/.ssh/known_hosts, удалив оттуда старый публичный ключ и добавив новый:

github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=


Автоматическое обновление ключа можно произвести следующей командой:

$ ssh-keygen -R github.com
$ curl -L https://api.github.com/meta | jq -r '.ssh_keys | .[]' | sed -e 's/^/github.com /' >> ~/.ssh/known_hosts

После корректного обновления вы увидите правильный отпечаток:

SHA256:uNiVztksCsDhcc0u9e8BujQXVUpKZIDTMczCvj3tD2s

Инфраструктура ключей SSH


Разберёмся, что произошло.

Все знают, как работает инфраструктура публичных ключей (PKI) и асимметричная криптография. Например, по протоколу TLS. У каждого сервера есть пара открытых/закрытых ключей. Когда вы заходите на сайт, он предъявляет TLS-сертификат с открытым ключом, а браузер производит ряд криптографических операций, чтобы проверить сертификат и сгенерировать эфемерный ключ для шифрования текущей сессии.

Эта инфраструктура используется практически для всех протоколов с применением TLS, включая SMTP и IMAP. Но SSH не использует TLS и не участвует в традиционной инфраструктуре PKI.

Вместо этого SSH использует модель Trust on First Use (TOFU). В первый заход на сервер вас спрашивают, доверяете ли вы его открытому ключу, вы обычно нажимаете кнопку «Да» и продолжаете жить дальше.

Всё это прекрасно работает до того момента, когда ключ меняется — и SSH начинает жаловаться на несоответствие и могло произойти что-то ужасное типа MiTM (кто-то перехватывает ваш трафик).

Следует проверить новые ключи и убедиться, что они легитимны. Это довольно утомительная процедура для обычных пользователей, поэтому многие просто нажимают «Да». В случае реальной MiTM-атаки злоумышленник рассчитывает именно на такое отношение.

Чем плохи текущие сертификаты SSH


Сразу возникает вопрос: почему не использовать сертификаты для хостов SSH?

OpenSSH действительно поддерживает сертификаты, но немного странным образом. У него собственный формат, который значительно проще формата сертификатов X509 в TLS.

По сути, сертификат SSH содержит следующее:

  • открытый ключ;
  • список имён хостов, для которых он подходит;
  • подпись центра сертификации.

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

В принципе, можно использовать обычные PKI-сертификаты для SSH, но это плохая идея, потому что противоречит существующим стандартам и методикам их применения.

Остаётся только одно: всегда использовать секретный ключ. Github — массовый сервис с тысячами серверов, и всем нужен доступ к одному закрытому ключу. Очевидно, девопсы отвечают за развёртывание этого закрытого ключа на новых системах по мере их ввода в эксплуатацию. Отсюда и риск, что ключ случайно окажется в неправильном месте (в открытом репозитории).

Что делать?


В текущей ситуации владельцам серверов/доменов можно порекомендовать только одно: как можно лучше защищать свои приватные ключи SSH.

Для простых ситуаций (некоммерческое использование) есть инструменты вроде утилиты melt для безопасного бэкапа и восстановления SSH-ключей.



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

Проблема в том, что HSM недостаточно быстры для обработки миллионов запросов, с которым работает Github. В такой ситуации некоторые специалисты рекомендуют развернуть службу HSM, которая будет ежеминутно выдавать серверам новый сертификат хоста SSH, подписанный закрытым ключом в HSM. Если клиенты настроены на доверие к ключу, которым подписываются сертификаты, то не имеет значения, какой закрытый ключ на серверах — клиент увидит, что есть действительный сертификат, и будет доверять ключу, даже если он изменится. Ограничение срока действия сертификата защищает от утечки ключа.

Чтобы такое стало возможным, нужно слегка изменить клиентский инструментарий, потому что в данный момент OpenSSH не имеет возможности делать TOFU для удостоверяющих центров, только для самих ключей. То есть нельзя сделать запрос ssh://git@github.com/whatever и получить запрос на доверие к УЦ Github. Можно только вручную добавить строку @cert-authority github.com (ключ) в файл known_hosts, а из пользователей практически никто не готов к таким операциям, так что польза от внедрения этой инфраструктуры будет незначительной.

Самое важное, что мы можем сделать для повышения безопасности экосистемы SSH — это упростить использование сертификатов, а это означает улучшение поведения клиентского софта, пишет специалист по безопасности и Linux-разработчик Мэттью Гарретт (Matthew Garrett). Он обращает внимание, что OpenSSH поддерживает протокол для ротации ключей. То есть у сервера может быть набор из нескольких доверенных ключей, которые клиент может кэшировать, а затем аннулировать старые ключи. Но всё-таки подход с сертификатами выглядит предпочтительнее как универсальное решение проблемы.

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



Комментарии (5)


  1. dartraiden
    09.04.2023 15:37
    +2

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

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


  1. netch80
    09.04.2023 15:37
    +2

    OpenSSH вообще очень странная штука.
    У меня были ситуации с ним, например, не принимает конкретный ключ в authorized_keys. Или автоматически первым пунктом зовёт auth=none, но так, что pam_unix видит проверку с пустым паролем для акаунта с реальным паролем и тормозит процесс на пару секунд, а sshd решает, что раз была задержка, надо её усилить, и добавляет ещё две секунды. Или из проб приватных ключей берёт только первые 4, а остальные пропускает (ну вот надо было в конфиге по умолчанию много ключей вписать). Код написан местами вредительски.
    А то, что все ключи надо собирать в один файл и свойства к ним писать в потенциально опасном формате? (там где no-agent-forwarding, forced_command и всё такое)


    Я бы даже сказал, что основная проблема с ним это безальтернативность. Есть, фактически, одна реализация на всех. Dropbear есть, но ограничен по свойствам. LSH по сути умер. Реализация от ssh.fi зохавана корпорастами.
    Почему, в отличие от 100500 других средств, нет альтернативных реализаций, например, от GNU или Apache?


    1. AlexanderplUs
      09.04.2023 15:37
      +1

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

      У обычного человека вполне понятное отношение к таким вещам: чем больше цена ошибки, тем меньше желание экспериментировать и рисковать.


      1. netch80
        09.04.2023 15:37

        Спрашивается, где найти желающих рисковать в таком чувствительном деле как управление сервером?

        Неее, не проходит такая логика. Потому что тогда была бы единственная система управления стартом/стопом (да, systemd занимает сейчас бо́льшую часть, но есть много возможностей ставить без него), единственный пакетный менеджер (а сейчас rpm+yum, rpm+dnf, deb+apt, pacman, и ещё десяток)...


        Или что, компиляция не ответственное дело? По-моему, более ответственное даже. Имеем GCC, Clang+LLVM, ICC, Open64 в двух клонах, и ещё парочку простейших, пригодных для контроля корректности компиляции.


        Или управление сетью — тоже критично для "управления сервером": даже не вспоминая облачные средства — на NetworkManager свет клином не сошёлся.


        Нет, тут что-то другое.


  1. V1p3rL0rd
    09.04.2023 15:37

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