Laboratorium 7 i 8: ssh, pgp

strict warning: Only variables should be passed by reference in /usr/share/drupal6/modules/book/book.module on line 559.

Kryptograficzna ochrona komunikacji i poczty na poziomie aplikacji

Patryk Czarnik
BSK 2009/2010, ostatnia aktualizacja MIchał Kutwin 2020/2021


Zobacz także

Temat opisują także scenariusze 7 i 8 na Ważniaku. Zwróć uwagę szczególnie
na niewymienione w bieżącym tekście polecenia programu gpg.

Przeczytaj (żeby wiedzieć jakie są możliwości, ale niekoniecznie znać na pamięć składnię i opcje):

man ssh, man ssh-keygen, man sshd_config, man gpg.

Warto przejrzeć (i wyłapać najważniejsze hasła) także:

man ssh_config, man ssh-agent, man scp, man rsync, man sftp, a także SSH i PGP na Wikipedii.


SSH

SSH (Secure Shell) to protokół zabezpieczający komunikację w warstwie aplikacji, którego podstawowym zastosowaniem jest zdalna praca przez konsolę tekstową. Może on być jednak używany także do innych celów, m.in. zdalnego używania aplikacji graficznych X Windows, bezpiecznego przesyłania plików, montowania zdalnych katalogów i tunelowania dowolnych połączeń TCP.

Zabezpieczenie komunikacji polega na:

  • uwierzytelnieniu serwera przez klienta: przy pierwszym połączeniu z danym serwerem wyświetla się pytanie o akceptację klucza publicznego serwera - zwykle wpisujemy wtedy "yes"; przy każdym kolejnym połączeniu weryfikuje się czy serwer używa tej samej pary kluczy, tzn. czy serwer posiada klucz prywatny pasujący do znanego nam klucza publicznego,
  • uwierzytelnieniu użytkownika przez serwer (różne metody),
  • szyfrowaniu przesyłanych danych,
  • podpisywaniu i weryfikacji każdego przesyłanego pakietu (ochrona przed podmianą danych oraz wykrywanie błędów transmisji).

Używać będziemy implementacji OpenSSH, której podstawowe pakiety to zwykle
openssh (instaluje go automatycznie każda znana mi dystrybucja) oraz
openssh-server (to już często trzeba doinstalować samodzielnie).

UWIERZYTELNIENIE UŻYTKOWNIKA

SSH oferuje kilka metod uwierzytelnienia, z najpopularniejszymi „password” (na podstawie hasła), „keyboard interactive” (bardziej ogólna metoda, w praktyce też najczęściej sprowadzająca się do podania hasła) oraz „public key” opisana w dalszej części.

Uwierzytelnienie za pomocą hasła

Używanie uwierzytelnienia opartego o hasło jest o tyle wygodne, że nie wymaga specjalnej konfiguracji. Natomiast obarczone jest wieloma wadami z punktu widzenia bezpieczeństwa oraz wygody:

  • hasło jest narażone na ataki oparte o jego zgadnięcie: atak siłowy („brute force”), słownikowy, „socjalny” (data urodzin, imię psa itp.), podsłuchanie tego samego hasła używanego w niechronionym protokole, podglądanie klawiatury (kamery!), itp.;
  • ponieważ hasło jest przesyłane (w postaci zaszyfrowanej), atak typu „man in the middle” (klient łączy się z nieprawdziwym serwerem, np. po przejęciu przez atakującego kontroli nad DNS czy routerem, a użytkownik zbyt pochopnie akceptuje tożsamość serwera) prowadzi do poznania hasła przez atakującego, który następnie może połączyć się z prawdziwym serwerem;
  • konieczność wielokrotnego wpisywania hasła w przypadku używania aplikacji takich jak cvs/svn/git.

Uwierzytelnienie oparte o klucze (metoda "public key")

Generujmy parę kluczy (programem ssh-keygen), klucz prywatny pozostaje po stronie klienta (w pliku .ssh/id_rsa lub .ssh/id_dsa), a klucz publiczny jest wgrywany na serwer. Klucze publiczne są zapisywane na serwerze jeden po drugim w pliku .ssh/authorized_keys na koncie tego użytkownika, na które chcemy się logować; do dodania klucza na serwer można użyć także narzędzia ssh-copy-id (po stronie klienta).

Standardowo używa się osobnego klucza prywatnego dla każdego komputera (i konta), z którego łączymy się ze światem, oraz wgrywa się odpowiadające klucze publiczne na te serwery i konta, do których chcemy się logować. Klucz prywatny można zabezpieczyć hasłem, co utrudni użycie klucza w przypadku przejęcia pliku z kluczem.

„Losowo” wygenerowany klucz nie jest narażony na ataki słownikowe, a atak siłowy, ze względu na długość klucza, wymaga ogromnych nakładów. Protokół SSH nie przesyła klucza prywatnego nawet w postaci zaszyfrowanej, co zabezpiecza przed atakiem "man in the middle". Wadą tego rodzaju uwierzytelnienia jest konieczność przechowywania plików z kluczami i chronienia plików z kluczami prywatnymi.

Zarządzaniem kluczami podczas jednej sesji lokalnej może zajmować się program ssh-agent, do którego często systemowy interfejs użytkownika (Gnome, KDE itp.) oferuje nakładki graficzne. Można też używać tekstowego polecenia ssh-add, aby na czas sesji zapamiętać otwarty klucz. Uwalnia to użytkownika od konieczności wielokrotnego wpisywania hasła odblokowującego klucz.

KONFIGUROWANIE SERWERA

OpenSSH pozwala dość dokładnie skonfigurować serwer i dostosować go do wymagań bezpieczeństwa, wygody i innych. Możliwe jest m.in. stosowanie ograniczeń na dostępne algorytmy, sposoby uwierzytelnienia, liczbę otwartych sesji itp. w zależności od użytkownika i hosta, z którego się łączy. Można także wymóc stosowanie uwierzytelnienia i limitów opartych o PAM (poprzednie zajęcia). Standardowo konfiguracja serwera zapisywana jest w pliku /etc/ssh/sshd_config.
Szczegóły: man sshd_config.

KONFIGUROWANIE KLIENTA

Większość opcji dla klienta SSH można podać bezpośrednio w wierszu poleceń, ale dla wygody można także zapisać je w pliku konfiguracyjnym, w razie potrzeby uzależniając konfigurację od serwera docelowego. Konfiguracja klienta SSH zapisywana jest w plikach /etc/ssh/ssh_config (domyślna dla systemu) i ~/.ssh/config (dla użytkownika).
Szczegóły: man ssh oraz man ssh_config

BEZPIECZNE PRZESYŁANIE PLIKÓW

Służą do tego protokoły i odpowiadające im aplikacje scp (najprostsza), sftp i rsync (bardziej zaawansowane), wewnętrznie używające protokołu SSH.

Cechą charakterystyczną sftp jest zbiór poleceń analogicznych do poleceń FTP, natomiast cechą charakterystyczną rsync jest różnicowe przesyłanie plików – sprawdzanie (poprzez porównywanie skrótów), które pliki lub bloki większych plików uległy zmianie i przesyłanie tylko tych zmienionych. Oba polecenia pozwalają przesyłać całe drzewa katalogów z możliwością filtrowania po rodzaju pliku, przenoszenia uprawnień itp.

Uwaga: SFTP jest niezależnie zdefiniowanym protokołem (funkcjonalnie wzorowanym na FTP), a nie jest tylko tunelowaniem zwykłego FTP w połączeniu SSH (ani tym bardziej SSL).

Pośrednio z SSH do transferu plików mogą korzystać także cvs, svn czy git.

MONTOWANIE KATALOGÓW

Wszyscy znamy (a przynajmniej powinniśmy) mechanizm NFS do tworzenia sieciowych systemów plików - montowania lokalnie katalogów serwera plików. Zwykły użytkownik może osiągnąć to samo: zamontować sobie katalog z innego komputera. Jedyny warunek: trzeba mieć konto na ,,serwerze''.

Do takiego ad hoc montowania służy program sshfs. Do zamontowania zdalnego
katalogu używamy polecenia

sshfs komputer:katalog punkt-montowania

Punkt montowania to katalog na lokalnym komputerze (najlepiej pusty ;-). Pierwszy argument to katalog na zdalnym komputerze w typowej notacji używanej przez scp itp. Trzeba mieć do niego odpowiednie prawa.

Od tego momentu cała struktura tego katalogu jest widoczna lokalnie. Polecenie akceptuje większość opcji ssh i jescze trochę, szczegóły jak zwykle w man.

Aby odmontować taki katalog piszemy

fusermount -u punkt-montowania

To polecenie zdradza rodzaj użytego ,,oszustwa'': korzystamy z modułu jądra FUSE (Filesystem in USErspace).

TUNELE

Bezpieczne tunelowanie połączeń TCP ogromnie zwiększa gamę zastosowań SSH. Istnieją dwa rodzaje tuneli ze względu na kierunek:

  • lokalne (opcja -L): połączenia do podanego lokalnego portu klienta są przekazywane na serwer SSH i stamtąd łączymy się z docelowym serwerem, np.

    ssh -L 1234:www.w3.org:80 students.mimuw.edu.pl

    spowoduje otwarcie na lokalnej maszynie portu 1234 do nasłuchiwania, a połączenie do tego portu zostanie przekazane (w tunelu) na students i stamtąd otwarte (już bez ochrony) do www.w3.org na port 80.

  • zdalne (opcja -R): połączenia do podanego portu na serwerze SSH są przekazywane na maszynę lokalną i z niej łączymy się z docelowym adresem, np.

    ssh -R 1234:localhost:8080 students.mimuw.edu.pl

    spowoduje, że na students zostanie otwarty do nasłuchiwania port 1234, a połączenia przychodzące do tego portu zostaną (w tunelu) przekazane na lokalną maszynę (z której wywoływaliśmy ssh) i tam (bo napisaliśmy localhost) zostaną skierowane do portu 8080.

    Uwaga: domyślna konfiguracja SSH (także na students) powoduje, że porty otwarte na serwerze nie są widoczne z zewnątrz, a jedynie poprzez lokalny interfejs loopback („localhost”); można to zmienić w konfiguracji serwera za pomocą opcji GatewayPorts.

Można także tworzyć w konfiguracji „urządzenia tunelowe” czy tunelować protokół SOCKS, w co się już nie wgłębiamy.

źródło obrazka: http://jakilinux.org/aplikacje/sztuczki-z-ssh-2-tunele/

PGP i GPG

OpenPGP to otwarty standard IETF oparty o wcześniejszy, obecnie częściowo komercyjny, produkt PGP (Pretty Good Privacy). Standard ten opisuje metody zabezpieczania poczty elektronicznej i plików. Podstawą jest użycie kryptografii klucza publicznego, a gdy przyjrzeć się szczegółom, okaże się, że używana jest także kryptografia klucza sekretnego ("szyfrowanie symetryczne"), bezpieczne funkcje haszujące ("skrót kryptograficzny"), kompresja oraz konwersja radix64.

Dwie najważniejsze funkcje to podpisywanie wiadomości (kluczem prywatnym nadawcy) i szyfrowanie wiadomości (kluczem publicznym odbiorcy). Do weryfikacji podpisu potrzebny jest klucz publiczny nadawcy, a do odszyfrowania wiadomości klucz prywatny odbiorcy. Podpisywanie i szyfrowanie mogą być stosowane niezależnie od siebie.

Przyjrzyjmy się operacjom nieco bardziej szczegółowo.
Podpisywanie polega na:

  • wyliczeniu skrótu z całej wiadomości,
  • zaszyfrowaniu skrótu kluczem prywatnym nadawcy,
  • dołączeniu do wiadomości zaszyfrowanego skrótu.

Szyfrowanie polega na:

  • wygenerowaniu (możliwie) losowego klucza sesji,
  • zaszyfrowaniu ciała wiadomości szyfrem symetrycznym używając klucza sesji; zazwyczaj przed szyfrowaniem wiadomość jest kompresowana, a po szyfrowaniu zamieniana na tekst konwersją radix64,
  • dołączeniu do wiadomości klucza sesji zaszyfrowanego kluczem publicznym odbiorcy; w przypadku wielu odbiorców nie ma potrzeby szyfrowania całej wiadomości osobno dla każdego z nich, osobno szyfrowany (kluczem publicznym każdego odbiorcy) jest jedynie klucz sesji.

Popularną otwartą implementacją standardu jest GnuPG. Pod Linuksem dostępne są polecenia: gpg i gpg2, którymi można wykonywać operacje na plikach (także zapisanych wiadomościach) i zarządzać kluczami.

Sama aplikacja może być także używana do wykonywania na plikach pojedynczych operacji – składników standardu PGP, z czego użyteczne może być np. szyfrowanie plików na dysku czy weryfikacja spójności plików pobranych z sieci (wykorzystywane przez menedżery pakietów rpm i deb).

Aby wygenerować klucz piszemy

gpg --gen-key

Inne popularne polecenia opisano w Ważniaku, a wszystkie w man gpg.

PGP W POCZCIE ELEKTRONICZNEJ

Użycie OpenPGP w poczcie elektronicznej (do czego został stworzony) jest wygodniejsze gdy użyjemy klientów poczty wyposażonych we wsparcie dla tego standardu. Przykładem może być Thunderbird z dodatkiem Enigmail. Pozwala on nie tylko na podpisywanie, weryfikację, szyfrowanie i odszyfrowanie wiadomości, ale także na zarządzanie kluczami PGP/GPG zainstalowanymi na naszym komputerze.

S/MIME

Standardem podobnym w idei i zastosowaniach do PGP jest S/MIME. Szyfrowanie i podpisywanie odbywa się na tej samej zasadzie. Różnica dotyczy zarządzania certyfikatami (wizytówki z kluczami publicznymi, często same podpisane innym kluczem): w S/MIME muszą być uwierzytelnione przez instytucję uwierzytelniającą i tworzą drzewo zaufania w modelu PKI (public key infrastructure), natomiast w PGP można używać certyfikatów wygenerowanych lokalnie, których wartość może być oceniana poprzez tzw. sieć zaufania (Web of Trust).
Schemat PKI zostanie zaprezentowany na przyszłych zajęciach na przykładzie protokołu SSL/TLS.