• Czas czytania ~8 min
  • 25.03.2024

SSH jest bardzo potężnym i elastycznym narzędziem, ale jak pokazuje praktyka, nie wszyscy rozumieją, jak działa i używają go poprawnie. Słowo Secure jest częścią skrótu SSH i jest jednym z kluczowych aspektów protokołu, ale często nie poświęca się wystarczającej uwagi bezpieczeństwu. W tym artykule chcę porozmawiać o kilku typowych błędach podczas pracy z SSH, a także o niektórych, które są często pomijane.

image

Существует несколько способов аутентификации пользователя:

  1. По паролю — стандартный механизм, но не самый надежный, я не буду заострять на нем внимание
  2. По ключу — самый надежный способ аутентификации, но это при условии, если правильно его использовать
  3. По IP адресу — режим совместимости. Привожу просто для справки, сомневаюсь, что кто-то будет использовать его в трезвом уме.

Szyfrowanie

asymetryczne SSH wykorzystuje szyfrowanie asymetryczne, co oznacza, że istnieją dwa klucze: klucz publiczny i klucz prywatny. Wiadomość można zaszyfrować za pomocą klucza publicznego i odszyfrować za pomocą klucza prywatnego. Klucz prywatny jest przechowywany w bezpiecznym miejscu, a klucz publiczny jest dostępny dla wszystkich. Ponadto możesz podpisać wiadomość kluczem prywatnym i zweryfikować ten podpis za pomocą klucza publicznego.

Jak widać na schemacie, po wymianie kluczy publicznych dwa węzły mogą bezpiecznie komunikować się ze sobą przez niezabezpieczony Internet.

Ponadto użytkownik może zostać uwierzytelniony przy użyciu tej pary kluczy.

Klucz publiczny użytkownika musi zostać dodany do pliku $HOME/.ssh/authorized_keys
W tym pliku może znajdować się wiele kluczy publicznych, z których wszystkie będą działać.

image

Ochrona przed atakami

MITM Atak MITM to rodzaj ataku w kryptografii, w którym atakujący potajemnie przekazuje i, jeśli to konieczne, zmienia komunikację między dwiema stronami, które uważają, że komunikują się ze sobą bezpośrednio. Jest to metoda naruszenia kanału komunikacyjnego, w której atakujący, łącząc się z kanałem między kontrahentami, ingeruje w protokół transmisji, usuwając lub zniekształcając informacje.

Jedną z głównych innowacji w drugiej wersji protokołu jest wbudowana ochrona przed atakami MITM.

image

Istotą ochrony jest to, że każda ze stron musi upewnić się, że druga strona jest dokładnie tą, której się oczekuje, a nie napastnikiem.

Parametr StrictHostKeyChecking i plik known_hosts są odpowiedzialne za ochronę MITM po stronie klienta (tj. w celu określenia, czy łączysz się z serwerem ).

Klucze publiczne serwerów są przechowywane w następujących plikach:
$HOME/.ssh/known_hosts jest plikiem niestandardowym,
/etc/ssh/ssh_known_hosts jest plikiem systemowym.

Każdy rekord w known_hosts jest ciągiem znaków, który zawiera pola i używa spacji jako separatora:

  1. одно или несколько имен серверов или IP-адресов, разделенных запятыми
  2. тип ключа
  3. открытый ключ
  4. любые дополнительные комментарии

W tym miejscu odbywa się "identyfikacja"

StrictHostKeyChecking=no|ask|yes 

serwera Wartości mogą być następujące:

  • Nie — połączenie nastąpi w każdym przypadku, co najwyżej otrzymamy ostrzeżenie, że połączenie nie jest bezpieczne. Często można go znaleźć we wszelkiego rodzaju zautomatyzowanych skryptach, takich jak autotesty i autodeploye, i tu właśnie leży główny problem: jeśli skrypt działa normalnie, użytkownik (administrator) nie zauważy niczego złego i nastąpi infekcja/kompromitacja.
  • ask — pytaj o nowe połączenie (wartość domyślna), jeśli rekord nie znajduje się jeszcze w known_hosts, a jeśli wyrazisz zgodę na połączenie, zostanie dodany nowy rekord
  • Tak — zawsze skanuj, najbezpieczniejsza opcja, którą zdecydowanie polecam stosować w zautomatyzowanych systemach. Połączenie jest nawiązywane tylko wtedy, gdy istnieje wpis w known_hosts

Co nam to daje:

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

Jeśli wszystko jest jasne z drugim punktem, to co z pierwszym?

Są tu co najmniej trzy opcje:Z mojego doświadczenia wynika, że

  1. Довериться случаю и согласиться на добавление нового ключа сервера
  2. Добавить флаг VisualHostKey=key, при этом клиент отобразит визуальное представление открытого ключа сервера, это представление уникально и облегчит запоминание ключа
  3. Флешка или открытые источники: это вариант для параноиков, однако, если компрометация системы может стоить десятков тысяч долларов, то это не лишне.

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

image
Если открытый ключ изменился

Сообщение о смене ключа может происходить по нескольким причинам:

  1. Изменился адрес сервера
  2. Изменился ключ сервера, например, при переустановке системы
  3. MITM атака

opcje 1 i 2 w sumie wynoszą 100%, ale nie można też wykluczyć punktu 3.

Oto przykład life hacka, który łączy podejście

curl https://server.com/ssh_fingerprint | tee -a ~/.ssh/known_hosts

internetowe i ssh Na pierwszy rzut oka nie jest to zbyt bezpieczne, jednak informacje te można uzyskać za pomocą

ssh-keyscan example.com

metody Jednak w pierwszej opcji dodatkowo weryfikujemy autentyczność otrzymanego klucza za pomocą protokołu HTTPS.

W przypadku ciągłej integracji/ciągłego wdrażania o znaczeniu krytycznym

ssh-keyscan example.com >> ~/.ssh/known_hosts

użycie kombinacji podczas inicjalizacji w połączeniu z atakami

StrictHostKeyChecking=yes

MITM może być niezawodnie chronione przed atakami MITM.

Wiele kluczy

Często można zaobserwować następujący wzór:

image

każdy serwer na kliencie ma swoje własne pary kluczy, a $HOME/.ssh/ to kompletny bałagan.

Z jednej strony jest to bezpieczniejsze niż użycie jednej pary kluczy klienta — jeśli jeden klucz zostanie naruszony, zagrożony zostanie tylko jeden system, a nie wszystkie te, z którymi pracował użytkownik.

Jednak, jak pokazuje praktyka, jest to ostatnia rzecz, którą kierują się użytkownicy, często po prostu postępują zgodnie ze wszystkimi instrukcjami krok po kroku:

ssh-keygen
...
...

Czasami obserwowałem sytuację, w której niektóre były pocierane przez inne bez zastanowienia.

image

Przypominamy, że jeśli masz paranoję na punkcie bezpieczeństwa, wystarczy mieć jedną parę kluczy, ale musisz ją odpowiednio zabezpieczyć.

Nawiasem mówiąc, o ochronie kluczy

image

Pomyśl o swoim prywatnym kluczu SSH jak o kluczu do mieszkania, w którym przechowywane są pieniądze. Nigdy nie widziałem bardziej nieostrożnej postawy niż w przypadku kluczy SSH. Jeśli użytkownicy są nawet mniej lub bardziej świadomi powagi zapisywania haseł, to tylko nieliczni myślą o tym, że nikt nie powinien mieć dostępu do klucza prywatnego.

Co można wyróżnić:

  1. Хранить ключ надо в безопасном месте, в идеале это шифрованное хранилище
  2. Никому не предоставлять доступ к ключу, скомпрометированный ключ компрометирует все системы где разрешен доступ по нему
  3. Шифрование приватного ключа увеличивает безопасность, т.к. при потере ключа необходимо еще получить пароль для его дешифрации, либо потратить время и вычислительные мощности на его взлом.
  4. Не забывать про установку корректных прав на файл ключа 400, кстати, это распространенная ошибка, когда клиент отказывается использовать ключ

Możesz zmienić lub dodać hasło za pomocą polecenia

ssh-keygen -p

SSH-Agent

Ale często zdarza się sytuacja, w której musisz udać się na serwer ze swoim kluczem i tam go użyć. Istnieją trzy rozwiązania tego problemu:

  1. Скопировать свой приватный ключ на сервер
  2. Сгенерировать новую пару ключей и прописать ее в качестве варианта доступа
  3. Использовать ssh-agent

Z mojego doświadczenia wynika, że użytkownicy wybierają dwie pierwsze opcje w 90% przypadków i jak już powiedzieliśmy: nie ma nic bardziej przerażającego, niż kompromitacja klucza.

Zalecam użycie trzeciej metody

image

: agent SSH przechowuje klucze prywatne i używa ich w razie potrzeby. Program (np. ssh), gdy potrzebuje użyć klucza prywatnego, nie robi tego sam, ale wywołuje ssh-agenta, który z kolei wykorzystuje dane o znanych tylko mu kluczach prywatnych. W ten sposób klucze prywatne nie są ujawniane nikomu, nawet programom. należące do użytkownika.

Polecenie ssh-agent tworzy plik gniazda o nazwie /tmp/ssh-XXXXXXXX/agent.ppid, za pośrednictwem którego agent się komunikuje. Do wszystkich procesów podrzędnych agent używa zmiennych środowiskowych SSH_AUTH_SOCK (gdzie przechowywana jest nazwa pliku gniazda) i SSH_AGENT_PID (gdzie przechowywany jest identyfikator procesu agenta), aby dostarczyć informacji o sposobie kontaktowania się z agentem.

Agent dostarcza informacje w formie, która jest łatwa w użyciu dla powłoki.

SSH_AUTH_SOCK=/tmp/ssh-XXt4pHNr/agent.5087; export SSH_AUTH_SOCK;
SSH_AGENT_PID=5088; export SSH_AGENT_PID;
echo Agent pid 5088;

Po określeniu przełącznika -c agent używa składni powłoki języka C. Domyślnie (i gdy przełącznik -s jest jawnie określony) używana jest składnia powłoki Bourne'a. Zmienne te muszą być ustawione w bieżącej powłoce, więc często łączy się wywołanie ssh-agent z poleceniem eval.

$ eval `ssh-agent`
Agent pid 5088

Agent działa, dopóki nie zostanie jawnie zakończony sygnałem lub wywołaniem

$ ssh-agent -k

Listę tajnych kluczy znanych agentowi można wyświetlić za pomocą tego samego polecenia ssh-add z przełącznikiem wiersza polecenia -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)

Przykład pracy z ssh-agent można zobaczyć poniżej

image

Ponadto agent rozwiązuje inny problem: jeśli zaszyfrowałeś klucz prywatny, nie będziesz proszony o podanie hasła za każdym razem, gdy uzyskasz do niego dostęp. Jeśli używasz agenta, musisz wprowadzić hasło tylko podczas dodawania klucza do agenta.

Konfiguracja lokalna

Gdybym za każdym razem, gdy oglądałem ciąg w formule

ssh -p 2022 [email protected] -o StrictHostKeyChecking=yes -i ~/.ssh/server.pem

, dostawałem rubla, już dawno mieszkałbym w Soczi.

Na komputerze lokalnym można znaleźć plik $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

W związku z tym możesz zapisać większość parametrów hosta w tym pliku i nie wprowadzać go za każdym razem.

Inne sposoby poprawy bezpieczeństwa

1. Korzystając z uwierzytelniania kluczowego, nie zapominaj, że nadal masz hasło i bez względu na to, jak chronisz swój klucz prywatny, atakujący będzie mógł odgadnąć Twoje hasło qwerty i zalogować się bez konieczności kradzieży klucza

Istnieje kilka rozwiązań:

  • Ustaw bardzo złożone hasło, które będzie trudne do odgadnięcia i przechowuj w bezpiecznym miejscu. Umożliwi to alternatywny sposób logowania.
  • Usuń hasło całkowicie, ale wtedy mogą wystąpić problemy z sudo i innymi rzeczami
  • Wyłączenie uwierzytelniania hasłem na serwerze, w rzeczywistości z reguły jest to zabronione dla użytkownika root. Jedyne, co pozostało do zrobienia, to wyłączenie dla wszystkich użytkowników.

PasswordAuthentication no w /etc/ssh/sshd_config

2. Możesz także wyłączyć korzystanie z ssh v1
Protokół 2 w pliku /etc/ssh/sshd_config

3. I pamiętaj, aby zablokować dostęp do SSH dla niezaufanych źródeł

na zaporze 4. W przeszłości radziłbym zmienić port ze standardowego 22 na inny, ale obserwując ile jest prób logowania się do niestandardowych portów, mogę jednoznacznie powiedzieć: nie jest to ochrona przed włamaniem.

5. Jeśli już rozważamy odgadnięcie hasła, to nie byłoby zbędne konfigurowanie fail2ban , aby ograniczyć próby odgadnięcia hasła.

6. Problemy i luki są okresowo znajdowane w protokole i bibliotekach, wiersz tutaj jest uniwersalnym podejściem — śledź aktualizacje oprogramowania i staraj się regularnie instalować przynajmniej poprawki bezpieczeństwa.

7. SSH-agent jest bezpieczniejszy niż samo kopiowanie plików, jednak może również zostać zhakowany, na przykład przez użytkownika root na serwerze. Dlatego zaleca się włączanie przekazywania tylko w przypadkach, gdy jest to konieczne.

Wnioski

Przeczytaj dokumentację, mówi wszystko, bez względu na to, jak wulgarnie to brzmi.
SSH jest bardzo bezpiecznym protokołem, ale błąd ludzki jest często głównym źródłem problemów, więc miej oko na bezpieczeństwo.

Użyte materiały
Ochrona za pomocą kluczy SSH
Zarządzanie kluczami SSH oparte na agencie

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

O

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

O autorze CrazyBoy49z
WORK EXPERIENCE
Kontakt
Ukraine, Lutsk
+380979856297