Ostatnio kilka osób pytało mnie jak uszczelnić serwery oparte na GNU\Linux w celu wystawienia ich na świat. Zasięgnąłem informacji przez Google’a i po polsku nie znalazłem całościowego poradnika krok po kroku jak to zrobić. Większość postów i publikacji dotyczyło jednej tematyki np. firewalla lub konfiguracji serwera SSH. Poniżej znajdziesz moją ściągawkę, którą z powodzeniem stosuje podczas wdrażania honeypotów i serwerów opartych o Linux’a.
W poście korzystam z Ubuntu Server 15.04, lecz procedury są uniwersalne i nie różnią się zbytnio na innych systemach będących pochodnymi Debiana.
Standardowa praktyka na początek, pozwalająca uchronić się przed dziurami i dostępnymi publicznie exploitami na nie. W środowiskach produkcyjnych polecam testować poprawki na osobnym serwerze i wdrażać je dopiero po udanych testach. Najważniejsze jest to, aby cyklicznie powtarzać ten proces 😉
sudo apt-get update sudo apt-get upgrade sudo apt-get autoremove
Podstawową zasadą zachowania szczelności każdego systemu operacyjnego jest używanie konta innego niż administracyjne (konto roota) do codziennej pracy oraz oczywiście dla usług. Przekładając to na praktykę, stworzymy dodatkowe konto użytkownika, korzystające z sudo do podnoszenia uprawnień.
Domyślnie Ubuntu 15.04 tworzy nowe konto użytkownika, więc możesz spokojnie pominąć ten krok.
Tworzenie konta:
sudo useradd -d /home/[nazwa_uzytkownika] -s /bin/bash -m [nazwa_uzytkownika]
Dodanie użytkownika do grupy sudo:
sudo usermod -a -G sudo [nazwa_uzytkownika]
Nadanie hasła dla konta:
sudo passwd [nazwa_uzytkownika]
Podstawą jest odpowiednio silne hasło – co najmniej osiem znaków, zawierające duże i małe litery, cyfry oraz znaki specjalne.
Osobiście używam haseł, które mają minimum 32 znaki (litery, cyfry, znaki specjalne oraz spacje). Do ich generowania i przechowywania używam menadżera haseł KeePass.
Ponieważ nasz użytkownik jest w grupie sudo, nie potrzebujemy możliwości logowania się na konto roota. Nie da sie ukryć, że usunięcie konta roota nie jest dobrym pomysłem, lecz jego zablokowanie już tak:
sudo passwd -l root
Jeżeli z jakiegoś powodu będziemy musieli je ponownie aktywować, wykorzystamy to samo polecenie, lecz z przełącznikiem -u:
sudo passwd -u root
Pierwszym krokiem ku szczelnej konfiguracji SSH, jest zapewnienie poufności uwierzytelniania za pomocą kluczy. Jest to, w pewnym scenariuszu, bardzo wygodne, gdyż nie musimy wpisywać hasła, ale niesie pewne zagrożenia o których napiszę później.
Generowanie klucza dla użytkownika:
ssh-keygen
Określamy lokalizację klucza:
Generating public/private rsa key pair. Enter file in which to save the key (/home/nazwa_uzytkownika/.ssh/id_rsa):
Podajemy passphrase, zgodnie z wytycznymi dla haseł kont systemowych (przypominam: co najmniej osiem znaków, zawierające duże i małe litery, cyfry oraz znaki specjalne):
Enter passphrase (empty for no passphrase): Enter same passphrase again:
Dlaczego używanie passphrase klucza jest ważne?
Hasło klucza zapewnia dodatkową warstwę ochrony w przypadku kiedy napastnik uzyska dostęp do systemu operacyjnego z którego logujesz się na serwer / serwera lub kiedy wykradnie Twój klucz.
Po po pomyślnej generacji klucza wyświetlony zostanie jego fingerprint oraz lokalizacja:
Your identification has been saved in /home/nazwa_uzytkownika/.ssh/id_rsa. Your public key has been saved in /home/nazwa_uzytkownika/.ssh/id_rsa.pub. The key fingerprint is: fd:23:bd:c4:f1:c9:2f:02:fe:a3:1d:1d:fc:f5:f4:63 The key’s randomart image is: +—[RSA 2048]—-+ | | | | | | | . . | | S . . o o| | .+ = =+| | …B =E+| | .+o+o..| | .o+o ..| +—————–+
Klucz publiczny na serwer kopiujemy za pomocą polecenia (zakładam, że jest na nim uruchomiony serwer SSH):
ssh-copy-id nazwa_uzytkownika@adres_ip_konfigurowanego_serwera
Podczas pierwszego połączenia pojawi się komunikat, odpowiadamy oczywiście twierdząco:
The authenticity of host ‘XXX.XXX.XXX.XXX (XXX.XXX.XXX.XXX)’ can’t be established. ECDSA key fingerprint is fd:fd:d4:f9:84:fe:71:64:e1:55:00:ad:d6:6d:22:fe. Are you sure you want to continue connecting (yes/no)? yes
Po znalezieniu klucza SSH w naszym katalogu domowym, zostaniemy poproszeni o hasło do serwera docelowego:
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed – if you are prompted now it is to install the new keys nazwa_uzytkownika@adres_ip_konfigurowanego_serwera’s password:
Pomyślne uwierzytelnienie owocuje takim komunikatem:
Number of key(s) added: 1
Now try logging into the machine, with: “ssh ‘nazwa_uzytkownika@adres_ip_konfigurowanego_serwera’” and check to make sure that only the key(s) you wanted were added.
Logujemy się na serwerze za pomocą polecenia:
ssh nazwa_uzytkownika@adres_ip_konfigurowanego_serwera
Podmieniamy plik /etc/sshd_config na ten plik konfiguracyjny uprzednio kasując rozszerzenie pliku i dostosowując pod siebie (zawarte są w nim komentarze dla łatwiejszego zrozumienia opcji):
sudo nano /etc/ssh/sshd_config
Restatrujemy serwer SSH:
sudo service ssh restart
Po konfiguracji SSH na innym porcie niż 22, możemy zainstalować wrappera na iptables znacząco ułatwiającego pracę z firewallem czyli UFW.
Instalacja UFW:
sudo apt-get install -y ufw
Otwarcie portów dla SSH i HTTP:
sudo ufw allow [port_skonfigurowany_w_sshd_conf] sudo ufw allow http
Blokada ruchu przychodzącego na innych portach:
sudo ufw default deny
Włączenie i aplikacja reguł firewalla:
sudo ufw enable
Wszystkie reguły filtrowania ruchu UFW podejrzymy za pomocą:
sudo ufw status verbose
Celem uniknięcia ataków na pamięć współdzieloną przez działające w systemie usługi, ustalimy bardziej restrykcyjne reguły dla tego mechanizmu IPC.
Otworzymy plik /etc/fstab:
sudo nano /etc/fstab
Dodajmy na samym końcu pliku poniższą linijkę:
tmpfs /run/shm tmpfs defaults,noexec,nosuid 0 0
Restart serwera:
sudo shutdown -r 0
Plik /etc/sysctl.conf jest odpowiedzialny za ustawianie parametrów jądra systemu, w tym punkcie ustalimy parametry stosu TCP/IP.
Otwórzmy plik /etc/sysctl.conf:
sudo nano /etc/sysctl
Po uprzednim dostosowaniu dodajmy następujące reguły z pliku pliku (zawarte są w nim komentarze dla łatwiejszego zrozumienia opcji).
Aplikacja reguł:
sudo sysctl -p
Domyślnie instalacja Ubuntu zawiera w sobie szereg niewykorzystywanych usług. Usługi te, oprócz tego, że alokują niepotrzebnie pamięć to również mogą stać się przyczyną zagrożenia w przypadku potencjalnego 0-day’a.
Generalnie starajmy ograniczać się liczbę wykorzystywanych usług na serwerze do minimum i nie budujmy serwerów na “masę”.
Wyświetlenie działających usług:
sudo initctl list | grep running
Usunięcie usługi z systemu:
sudo apt-get purge nazwa_usługi
Instrukcję krok po kroku (instalacja + generowanie kluczy + konfiguracja) znajdziesz tutaj.
PSAD jest systemem IDS, który analizuje logi firewalla, celem wykrycia podejrzanego ruchu (na przykład skanowania portów) i jego zablokowania. Jeżeli chciałbyś dowiedzieć się więcej na temat PSAD to polecam ten artykuł.
Instalacja PSAD:
sudo apt-get install -y psad
Otwórzmy plik konfiguracyjny /etc/psad/psad.conf:
sudo nano /etc/psad/psad.conf
Podmieńmy /etc/psad/psad.conf na ten plik
Dodajmy reguły iptables niezbędne do poprawnego działania PSAD:
sudo iptables -A INPUT -j LOG sudo iptables -A FORWARD -j LOG
Przeładowanie konfiguracji PSAD:
sudo psad -R
Aktualizacja sygnatur atakaów:
sudo psad –sig-update
Ponowne uruchomienie PSAD:
sudo psad -H
Logwatch jest bardzo przydatnym narzędziem, analizującym logi systemowe oraz usług i generującym czytelny raport. Dodatkowo udostępnia mnóstwo opcji konfiguracyjnych pozwalającym dowolnie konfiugrować sobie zakresy analizy, czasu, i tym podobnych.
Instalacja:
sudo apt-get install -y logwatch
Wyświetlenie raportu od czasu instalacji:
sudo logwatch –range all
Jeżeli czegoś brakuje Ci w moim poście, znasz jakieś inne sposoby na polepszenie ogólnopojętego bezpieczeństwa serwerów Linux to komentarze są do Twojej dyspozycji. Chętnie odniosę się do wszystkich merytorycznych komentarzy 🙂