Pytanie rzadko pojawia się bez powodu. Serwer zaczął działać wolniej, hostingodawca napisał o ruchu wychodzącym albo w poczcie znalazło się powiadomienie o logowaniu, którego nikt nie wykonywał. Potem zaczyna się najbardziej nieprzyjemna część: nie wiadomo, co sprawdzać i w jakiej kolejności, a pierwszy odruch — skasować wszystko i postawić od nowa — jest niemal zawsze przedwczesny.
Poniżej kolejność sprawdzania, która zajmuje jakieś dwadzieścia minut i w większości przypadków daje jednoznaczną odpowiedź. Idzie od najtańszego do najdroższego: najpierw to, co widać od razu, potem to, co wymaga porównania.
Krok pierwszy: kto się logował
Zacznijmy od logowań. Jeśli ktoś obcy dostał się do środka, prawie na pewno wszedł przez SSH i został ślad.
last -20
lastb | head -20
who
last pokaże ostatnie udane logowania, lastb — nieudane, who — kto jest zalogowany w tej chwili. Liczy się nie liczba, lecz kształt. Tysiące nieudanych prób z adresów, które nigdy nie wracają, to zwykłe tło; dzieje się tak na każdym publicznym adresie nieprzerwanie i nic nie znaczy.
Niepokojące jest co innego:
- udane logowanie z adresu, pod którym nie ma nikogo z zespołu;
- logowanie na nazwę użytkownika, której nikt nie zakładał;
- nieudane próby na nazwę, która na tej maszynie faktycznie istnieje — to znaczy, że ktoś zna listę użytkowników, a nie leci ze słownika;
- sesja otwarta w tej chwili, której nikt z zespołu nie otwierał.
Osobno warto sprawdzić, czy nie pojawiły się obce klucze. Plik ~/.ssh/authorized_keys to najczęstszy sposób na utrwalenie dostępu: hasło można zmieniać dowolnie wiele razy, klucz zostanie.
cat ~/.ssh/authorized_keys
sudo cat /root/.ssh/authorized_keys
Każdy wiersz to czyjś dostęp. Jeśli nie da się powiedzieć czyj, należy uznać go za obcy.
Krok drugi: co zmieniło się w systemie
Włamanie prawie zawsze zostawia ślady na dysku: podmieniony plik wykonywalny, dopisany wiersz w konfiguracji, nowy plik w katalogu serwera WWW. Sprawdzanie tego wzrokiem nie ma sensu — potrzebny jest wzorzec.
W Debianie i Ubuntu wzorzec już istnieje: każdy pakiet zna sumy kontrolne swoich plików.
sudo apt install debsums
sudo debsums -c
Polecenie wypisze pliki różniące się od tego, co zainstalowała dystrybucja. Część znalezisk będzie uzasadniona — pliki konfiguracyjne w /etc po to właśnie istnieją, żeby je zmieniać. Natomiast zmieniony plik wykonywalny w /usr/bin, /usr/sbin czy /bin na serwerze, którego nikt nie ruszał ręcznie, to już inna rozmowa.
Drugie źródło to świeże pliki tam, gdzie ich być nie powinno. Webshell zwykle leży w katalogu przesyłanych plików i wygląda jak niewinny .php:
find /var/www -type f -name '*.php' -mtime -14 -ls
Czternaście dni to tylko punkt wyjścia; należy wstawić okres, w którym na pewno nic nie było publikowane.
Krok trzeci: co wychodzi na zewnątrz
Zhakowany serwer rzadko przejmuje się dla niego samego. Używa się go: do rozsyłania spamu, do kopania kryptowalut, do wchodzenia w cudze sieci, do trzymania cudzych plików. Wszystko to tworzy połączenia wychodzące, których wcześniej nie było.
ss -tulpn
ss -tp state established
Pierwsze polecenie pokaże, co nasłuchuje, drugie — co jest zestawione teraz. Czytać należy kolumnę z procesem. Wątpliwości budzą: nieznany proces nasłuchujący na 0.0.0.0; połączenia wychodzące na wysokie porty do adresów, z którymi aplikacja nie ma nic wspólnego; a zwłaszcza proces uruchomiony z /tmp albo /dev/shm — z tych katalogów nie uruchamia się nic legalnego.
Przy okazji warto spojrzeć na obciążenie. Koparka zdradza się tym, że procesor jest zajęty bez przerwy, a witryna nie cieszy się żadną popularnością.
Jeśli oznaki się potwierdzą
Pierwszy odruch to szybko posprzątać: usunąć obcy klucz, zabić proces, skasować plik. Tak robić nie należy, bo zniszczy się to, po czym można by później zrozumieć, którędy wszedł. A jeśli tego nie zrozumiemy, wróci — i to być może jutro.
Kolejność, która chroni i dane, i obraz sytuacji:
- Zrobić migawkę dysku u hostingodawcy, jeśli jest taka możliwość. To jedyny krok, którego później nie da się powtórzyć.
- Odciąć maszynę od sieci albo zamknąć wszystko poza własnym adresem IP — ale nie wyłączać. Przy wyłączeniu tracimy listę procesów i otwarte połączenia, a to połowa dowodów.
- Zapisać dzienniki na zewnątrz:
/var/log/auth.log, dzienniki serwera WWW, wynik trzech powyższych poleceń. - Dopiero teraz ustalać, jak uzyskano dostęp.
Instalacja od zera to właściwe zakończenie, jeśli dostęp uzyskano z uprawnieniami roota. Żadne czyszczenie nie daje gwarancji, że nic nie zostało. Ale instalowanie od nowa bez zrozumienia przyczyny nie ma sensu: ta sama dziura wróci na świeży system.
Żeby pytanie nie pojawiało się nagle
Wszystko powyższe to jednorazowe ręczne sprawdzenie i odpowiada na pytanie „co dzieje się w tej chwili”. Kłopot w tym, że zadaje się je zwykle późno: kiedy hostingodawca już napisał albo witryna przestała działać.
Każde z tych sprawdzeń istnieje jako osobne narzędzie, które potrafi obserwować stale: nieudane logowania — fail2ban, zmiany plików — AIDE, integralność pakietów — debsums, otwarte porty — regularna migawka ss. Zainstalować je osobno nie jest trudno; trudniej przyzwyczaić się do codziennego czytania sześciu różnych wyników — dlatego w praktyce nikt ich nie czyta.
Na tym właśnie polega sens zebranego panelu: te same dane, ale na jednej stronie i z historią, żeby „wczoraj było inaczej” było widoczne bez osobnej wyprawy. Poniżej strony demonstracyjne pokazujące, jak to wygląda w całości.