SSH: Identyfikacja serwera
Napisał: Damian Zelek
15/08/2009 w Bezpieczeństwo Brak komentarzy. (artykuł nr 127, ilość słów: 1988)
W
szyscy używamy / korzystamy z połączeń SSH. Dzięki temu protokołowi jesteśmy w stanie w bezpieczny sposób łączyć się z inną maszyną i wykonywać na niej w zdalny sposób komendy. Jesteśmy także w stanie przesyłać bezpiecznie pliki (SCP), a nawet tworzyć o niebo bezpieczniejszą alternatywę dla FTP (RSSH + SCPOnly), czy tworzyć szyfrowane tunele itp. Jednak wiele osób nie zdaje sobie sprawy z tego, iż chociaż SSH szyfruje przesyłane dane to dla atakującego wcale nie jest problemem podsłuchać Naszą sesję. Podsłuchiwanie to z powodu szyfrowania sesji przybiera trochę inny kształt: atakujący może symulować serwer, z którym chcemy się połączyć. Dzięki symulowaniu serwera będzie w stanie Nas “podsłuchiwać”, ponieważ chociaż dane są szyfrowane to de fakto będą one przechodziły (lub adekwatnie od intencji atakującego — dochodziły) przez “niepowołaną” maszynę. Jest to tzw. atak typu Man-In-The-Middle. Artykuł ten ma na celu przybliżenie sposobu ochrony Naszej szyfrowanej sesji SSH dzięki kluczom identyfikacyjnym serwera.
Krótkie omówienie ataku Man-In-The-Middle:
Prywatna sieć oparta o NAT Internet | [ Komputer 1 ]--\ | \--| Brama NAT | | [ Komputer 2 ]------| przejęta |-----[ Zdalny serwer ] /--| przez intruza | | [ Komputer 3 ]--/ | |
Jak widzimy na powyższym przykładzie Nasza maszyna (przyjmijmy, że jest to Komputer 2) chciała się połączyć zdalnie z serwerem. Jednak na drodze połączenia stanął komputer atakującego (ponieważ zarówno Nasz komputer jak i atakującego są w jednej i tej samej sieci wewnętrznej opartej o Network Address Translation, a dodatkowo komputer przejęty przez intruza pełni rolę gateway’a – czyli bramy udostępniającej internet reszcie komputerów w sieci LAN – to wcale nie było to trudne, a wręcz trywialne). Gateway, który jest pod kontrolą agresora, jest w stanie imitować serwer usługi, z którą chcemy się połączyć. Jeżeli do tego dojdzie, będziemy połączeni z maszyną włamywacza myśląc, iż jesteśmy połączeni z docelowym serwerem. Wszystkie dane (łącznie z hasłem użytym podczas logowania) przechwyci intruz. Tylko od niego zależy, czy chce uzyskać tylko i wyłącznie hasło “na szybko” czy też, bardziej prawdopodobnie, będzie chciał przejąć i korzystać z Naszego konta na zdalnym serwerze. Jeżeli tak, to w tym celu będzie on odbierał wszystkie Nasze pakiety, analizował je i przesyłał dalej do serwera. Dzięki takiemu działaniu nieświadomy “użytkownik” nie będzie nawet podejrzewać, iż coś jest nie tak. Należy tu także wspomnieć, iż włamywacz wcale nie musi przejąć naszej bramy. Może użyć technik, które pozwolą to pominąć…
Identyfikacja serwera:
Standardowo SSH udostępnia Nam możliwość “obrony” przed powyższym atakiem (oraz wieloma innymi). Jest to możliwe dzięki temu, iż klient SSH podczas łączenia się z serwerem sprawdzi jego klucz (weryfikujący tożsamość serwera). Klucz ten w bazie Naszego klienta może znaleźć się na kilka sposobów:
- najbezpieczniejszym sposobem jest skontaktowanie się z administratorem serwera, z którym chcemy się połączyć i prośba o podanie klucza SSH (mądrym rozwiązaniem ze strony administratora jest stworzenie strony internetowej szyfrowanej za pomocą np. SSL, na której będzie dostępny klucz),
- ręczne wprowadzenie klucza dostępnego od osób trzecich (np. znajomy, który także posiada konto na danym serwerze i łączy się z nim za pomocą protokołu SSH),
- akceptacja klucza przy pierwszym połączeniu,
To ostatnie jest najczęściej stosowanym rozwiązaniem. Łącząc się pierwszy raz z danym serwerem, dostaniemy ostrzeżenie, iż nie posiadamy w swojej bazie klucza owego serwera (Listingi poniżej). Teraz od Nas zależy czy zaufamy serwerowi bądź nie. Często zatwierdza się tę decyzję i od tej pory, jeżeli ktoś stanie na drodze pomiędzy Nami, a serwerem dostaniemy ostrzeżenie, iż klucz, który dostaliśmy od serwera (tak naprawdę od usługi na komputerze atakującego) nie zgadza się z tym, który jest w Naszej bazie kluczy. W ten sposób wykryliśmy próbę ataku! (tzn. nie do końca, ale o tym później). W przypadku, gdy używamy programu PuTTY, który jest bezpłatną implementacją klienta usług Telnet, SSH oraz Rlogin, głównie używanym w systemach operacyjnych z rodziny Microsoft Windows do łączenia się z serwerami Uniksowymi komunikat ostrzegawczy objawi się nam w formie okna dialogowego posiadającego mniej więcej taką treść:
The server's host key is not cached in the registry. You have no guarantee that the server is the computer you think it is. The server's rsa2 key fingerprint is: ssh-rsa 1024 52:2a:b3:92:a6:88:ca:c0:ff:c2:1b:d1:53:11:fc:4e If you trust this host, hit Yes to add the key to PuTTY's cache and carry on connecting. If you want to carry on connecting just once, without adding the key to the cache, hit No. If you do not trust this host, hit Cancel to abandon the connection.
W przypadku użycia klienta SSH w systemie Linux, sytuacja przedstawia się następująco:
[jimmy@localhost jimmy]$ ssh zdalnyserwer.org The authenticity of host 'zdalnyserwer.org (12.34.56.78)' can't be established. RSA key fingerprint is e8:6c:76:4c:86:6b:b7:7a:d2:3a:88:ca:c0:54:e0:9b. Are you sure you want to continue connecting (yes/no)?
Pierwsze podejście:
Zobaczmy jak wygląda typowe połączenie:
[jimmy@localhost jimmy]$ ssh -l jimmy zdalnyserwer.org The authenticity of host 'zdalnyserwer.org (12.34.56.78)' can't be established. RSA key fingerprint is 66:20:75:1a:49:a9:73:b7:29:d3:0c:18:64:68:d6:73. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'zdalnyserwer.org, 12.34.56.78' (RSA) to the list of known hosts. Password: Last login: Thu Dec 2 23:12:20 2006 from 87.65.43.21
Łączymy się z serwerem po raz pierwszy, więc dostaliśmy ostrzeżenie o nieznanym kluczu. Załóżmy, iż ufamy temu serwerowi i połączymy się (wybierzemy opcję YES). Jak widać na powyższym listingu Nasz system dodał klucz owego serwera na stałe do “bazy danych kluczy“. Przy następnym połączeniu nie powinniśmy dostać żadnych ostrzeżeń (jeżeli dostaniemy to będzie znaczyło to iż najprawdopodobniej ktoś “imituje” serwer i w takim przypadku NIE wyrazimy zgody na dokończenie połączenia, a tym samym nie staniemy się łupem dla włamywacza).
W momencie akceptacji połączenia Nasz klient SSH zapisał klucz serwera w Naszym systemie w pliku $HOME/.ssh/known_hosts ($HOME jest zmienną aktualnej ścieżki do Naszego macierzystego katalogu). To właśnie ten plik jest Naszą bazą kluczy, która przechowuje wszystkie zatwierdzone bądź ręcznie wprowadzone klucze. Przykładowa wpis w tym pliku wygląda tak:
zdalnyserwer.org,12.34.56.78 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAt2cX8Lpo9eDGUxv5Q5iEnuLOeu7xiyMwuPZcE Uwav5GIwgVqW1JOnJwLOZVLjRpilI+crKR3DHH3BBQDgIPfZRPJRVtjT4hztGJZFvkDX jDehz8VaqsaXQS4kFZDBGQtdufe6ng7f4RNmy6ibPu4T2D3bbpI+2G0GStMyaj77kE=
Budowa pliku składa się kolejno z poszczególnych wpisów akceptacji. Z kolei zaś poszczególne wpisy są bardzo intuicyjne i łatwe do zrozumienia. Składają się z: host/IP serwera, określenie typu klucza oraz sam klucz publiczny. Istnieje także druga “baza kluczy”, ale o innym priorytecie. Baza znajduje się w /etc/ssh/ssh_known_hosts. Przechowuje ona hosty mające potwierdzenie z poziomu administratora (czyli odgórnie). Do modyfikacji pliku należy użyć odpowiedniego parametru w pliku konfiguracyjnym klienta ssh (/etc/ssh/ssh_config).
Rodzaje kluczy:
Wyróżniamy 3 rodzaje kluczy: SSHv1 RSA (rsa1), SSHv2 RSA (rsa) i SSHv2 DSA (dsa). Opcje odnośnie tych kluczy i ich używania znajdziemy w pliku konfiguracyjnym SSH /etc/ssh/sshd_config (m.in. możliwość ładowania tylko określonych kluczy [RSAAuthentication yes] – włączenie tych bardziej bezpiecznych). Po zainstalowaniu OpenSSH wszystkie 3 klucze powinny zostać stworzone w standardowej procedurze automatycznej. Jeżeli tak się nie stało możemy tworzyć je ręcznie:
ssh-keygen -t rsa /etc/ssh/ssh_host_rsa_key
Zamiast rsa możemy oczywiście podstawić rsa1 i dsa… Wzmianka o rodzajach kluczy jest niezbędna do zrozumienia poniższej sekcji.
Kiedy ktoś podsłucha naszą sesję:
Jak już wspominałem wcześniej nie jest zadaniem wcale trudnym podsłuchanie / przejęcie Naszej sesji SSH przez osobę z Naszej sieci. Do tego celu stworzono kilka dobrych programów “gotowców”, więc każdy początkujący “hakier” lub nawet wścibski kolega z sieci będzie w stanie Nas przechwycić. Pamiętajmy o jednym – będzie w stanie Nas przechwycić tylko za sprawą Naszej własnej głupoty poprzez akceptację nieznanego klucza z Naszej strony. Jeżeli jesteś przezorny sekcja ta, nie jest dla Ciebie. Jeżeli jednak miała miejsce wpadka (przypadkowe / nieumyślne zaakceptowanie nieznanego klucza MIMO ostrzeżenia) sprawa nie jest jeszcze całkowicie przegrana. Można sprawdzić czy atak naprawdę miał miejsce.
Zacznijmy od tego, iż zmiana klucza wcale nie musi oznaczać próby ataku. Do jego zmiany może dojść także z powodu:
- zmiana IP/host/DNS serwera
- nieudolny reinstal systemu
- update/upgrade ssh
- zmiana protokołu między SSHv1 i SSHv2
Teraz, jak wychodzić z opresji?. Dzień, jak co dzień, normalne logowanie w celu sprawdzenia poczty…
[jimmy@localhost jimmy]$ ssh zdalnyserwer.org @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ 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 the RSA host key has just been changed. The fingerprint for the RSA key sent by the remote host is e8:6c:76:4c:86:6b:b7:7a:d2:3a:88:ca:c0:54:e0:9b. Please contact your system administrator. Add correct host key in /home/jimmy/.ssh/known_hosts to get rid of this message. Offending key in /home/jimmy/.ssh/known_hosts:2 RSA host key for zdalnyserwer.org has changed and you have requested strict checking. Host key verification failed. [jimmy@localhost jimmy]$
A jednak nie! Klucz SSH się zmienił. Musimy zapisać RSA fingerprint (ten długi ciąg oddzielony dwukropkami). Następnie logujemy się (jak widać i tak musimy się zalogować, czyli nawet jeżeli do ataku doszło kilka dni wcześniej, a my dopiero teraz zdaliśmy sobie sprawę z powagi sytuacji to “fałszywy” klucz został zapisany do Naszego known_hosts, a za pomocą komendy ssh-keygen można “otrzymać” RSA fingerprint — czyli de fakto, także możemy sprawdzić czy to był atak czy też nie). Po zalogowaniu przechodzimy do katalogu /etc/ssh i listingujemy wszystkie pliki *.pub
ls *pub ssh_host_dsa_key.pub ssh_host_key.pub ssh_host_rsa_key.pub
Odpowiednie użycie komendy ssh-keygen + odpowiedni plik *.pub zwróci Nam fingerprint klucza. Zastanówmy się przez chwilę, który plik *.pub wybrać. Jeżeli wiemy, iż korzystamy ze starszej wersji protokołu SSHv1 będzie nam potrzebny plik ssh_host_key.pub. Dla RSA fingerprint użyjemy pliku z “rsa” w nazwie, a analogicznie do DSA fingerprint użyjemy pliku z “dsa” w nazwie. Wybór nie jest obojętny: musimy wybrać zależnie DSA lub RSA odwołując się do ostrzeżenia, które dostaliśmy na początku:
... RSA key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d. ...
Jak widać tutaj był RSA fingerprint więc komenda wyglądałaby tak:
ssh-keygen -lf /etc/ssh/ssh_host_rsa_key.pub
Jeżeli RSA fingerprint teraz uzyskany zgadza się z tym wyświetlonym podczas logowania (lub analogicznie z tym, który został w Naszym known_hosts) to znaczy to, iż wszystko jest na swoim miejscu. W innym wypadku prawdopodobnie staliśmy się celem ataku – należy szybko skontaktować się z administratorem serwera w celu zmiany hasła bądź ewentualnego wyjaśnienia przyczyny zmiany kluczy publicznych bez wcześniejszego powiadomienia Nas o tym. Należy także zaznaczyć, iż będąc zwykłym “użytkownikiem” z kontem shell na jakimś serwerze mamy zapewniony dostęp do plików *.pub w /etc/ssh i komendy ssh-keygen. Tak więc jest dana Nam możliwość SAMODZIELNEGO sprawdzenia czy staliśmy się ofiarą intruza czy też nie….
Hacking zmorą użytkownika:
Opisany wyżej sposób “detekcji powłamaniowej” działa jeżeli atak był przeprowadzany przez niedoświadczonych włamywaczy / script-kiddiez. Jest wiele bardziej zawiłych technik, dzięki którym taka detekcja jest ograniczona lub niemożliwa. Podczas wielu takich prób wykonywanych przeze mnie wystarczy wspomnieć, chociaż o analizie pakietów odbieranych przez intruza, a wysyłanych potem do serwera ze szczególnym naciskiem na pochodne logout, ssh-keygen bazujące na połączeniu in-out (tak, aby fingerprint usługi zwracany był z serwera, a nie usługi na komputerze atakującego), etc. Dlatego należy zdać sobie sprawę z tego, iż nigdy nie będziemy w 100% bezpieczni. Jednak dobrą przeszkodą dla włamywacza będzie stosowanie się do paru zasad:
- UNIKANIE logowania w wypadku, gdy klucz się nie zgadza
- ręczne wpisywanie kluczy do known_hosts i tylko z pierwszej ręki (np. administrator, serwisant; jeżeli administrator zdaje sobie sprawę z tego, iż prawdopodobnie nie będzie miał czasu na każdorazowe podawanie *fingerprint klucza powinien postarać się o wcześniej wspomniane wystawienie klucza na szyfrowanej via SSL stronie www bądź rozważenie możliwości użycia /etc/motd jako “informatora”)
- ustawienie opcji StrictHostKeyChecking= w pliku konfiguracyjnym klienta (/etc/ssh/ssh_config lub w konfiguracji w $HOME/.ssh) tak aby wskazywała na yes (w takim wypadku zły klucz lub jego brak uniemożliwi logowanie — dzięki temu zyskamy ochronę przed Naszą własną głupotą / nieuwagą, a nawet więcej); ochrona taka została zaprezentowana na listingu powyżej (możliwość zalogowania / połączenia została Nam “odebrana”).
Więcej informacji: man sshd_config, PuTTy docs