NFsec Logo

Portsentry – własny strażnik portów

12/02/2005 w Bezpieczeństwo Brak komentarzy.  (artykuł nr 9, ilość słów: 4056)

Z

awsze są dwie strony medalu. Skanery to bardzo przydatne narzędzia bezpieczeństwa, ale mogą zostać użyte w złym zamiarze – pozwalają na szybką ocenę słabości systemu. Dlatego przedmiotem tego artykułu jest program PortSentry autorstwa Craiga H. Rowlanda z dawnej firmy Psionic Software. Był on częścią pakietu oprogramowania Abacus do ochrony systemu przed włamaniami (aktualnie jest on rozwijany wyłącznie przez jego autora). PortSentry jest to zaawansowane narzędzie, do monitorowania, którego działanie nie mieści się w wąskiej definicji skanera portów, lecz wykrywania skanowania portów systemów i odpowiednie reagowanie.

Program ten próbuje w czasie rzeczywistym rozpoznać atak i doprowadzić do jego zablokowania. Do jego funkcji możemy zaliczyć:

  • zaawansowane wyszukiwanie skanowania utajnionego za pomocą pakietów FIN, półotwartych połączeń, ciągów NULL, pakietów niepoprawnie skonstruowanych, SYN i ataków w stylu X-MAS,
  • jednoczesne monitorowanie protokołów TCP i UDP na wielu gniazdach nawet z poziomu jednego procesu tego programu,
  • zapisywanie stanu (pamiętanie hostów, które już się łączyły z naszym serwerem), co pozwala na automatyczne dopisywanie hostów atakujących do wpisu deny w konfiguracji TCP Wrappers, ipchains, iptables.

  Jedną z mocniejszych stron PortSentry jest tryb Advanced Stealth Scan Detection Mode (zaawansowane wykrywanie skanowania). Polega ono na rozpoznawaniu portów nasłuchu serwera i sprawdzaniu prób połączeń jedynie do tych portów, które nie są w danym momencie czynne. Dzięki temu działanie programu nie obciąża zbytnio CPU (procesora) komputera i nie ma większego wpływu na jego wydajność. Inną jego zaletą w porównaniu do większości innych monitorów sieci jest możliwość śledzenia adresów IP intruza w funkcji czasu. Dzięki temu rozwiązaniu można zareagować na skanowanie portów wykonane przez “recydywistę” lub podjąć inne działania na podstawie częstotliwości, z jaką podejmowane są próby skanowania systemu z pewnego adresu. PortSentry choć nie jest objęty licencją GPL (lecz CPL), użytkownicy indywidualni i firmy mogą zainstalować go do użytku wewnętrznego. Choć witryna WWW firmy Psionic została zamknięta, to program można pobrać z wielu serwerów WWW i FTP. Aby rozpocząć proces instalacji należy pobrać najnowszą wersję z witryny: http://sourceforge.net/projects/sentrytools/. Aby zainstalować pobraną wersję (aktualną jest 1.2) wpisujemy następujące polecenia:

tar -xzovf portsentry-1.2.tar.gz
rm portsentry-1.2.tar.gz
cd portsentry_beta

Kompilacja programu pod Linuksem nie przedstawia trudności, jednak za nim do niej przystąpimy upewnijmy się, że w pliku źródłowym portsentry_config.h zgadzają się ustawienia dla zmiennych: CONFIG_FILE – ścieżka do pliku konfiguracyjnego – standardowo – /usr/local/psionic/portsentry/portsentry.conf i WRAPPER_HOSTS_DENY – ścieżka do pliku wrappera – standardowo – /etc/hosts.deny – plik ten jest używany tylko wtedy, gdy opcję blokady ustawimy na TCP Wrappers, zamiast skorzystać z bardziej efektywnych metod, takich jak IP Chains, czy IP Tables. Warto wspomnieć, że w aktualnie omawianej wersji dodano obsługę jądra 2.4, modułu IP Tables i masek sieciowych. Po dokonaniu lub nie, edycji możemy przystąpić do instalacji:

make linux (dla Debiana debian-linux)
make install
cp ignore.csh /usr/local/psionic/portsentry/

  W wersji 1.2 beta podczas kompilacji istnieje błąd związany z kodem w linii 1585. Spowodowany jest on tym, iż w pliku portsentry.c tekst zawarty w jednej z funkcji printf jest podzielony na dwa wiersze. By naprawić ten błąd wystarczy klawiszem backspace cofnąć wiersz tekstu “sourcefore dot net>\n”);” na wysokość poprzedniego – tak by cały test był zapisany w jednym ciągu.

  Instalacja PortSentry przebiega standardowo – pliki wchodzące w skład pakietu PS są umieszczane w nowo utworzonym katalogu /usr/local/psionic/portsentry. Jak widzimy po instalacji do katalogu portsentry został dodatkowo skopiowany skrypt “ignore.csh” (do jego obsługi należy posiadać zainstalowaną powłokę tcsh) – służy on do automatycznego dopisywania adresów IP hostów lokalnych (interfejsów), które mają być ignorowane przy wykrywaniu skanowania. Skrypt ten szczególnie jest przydatny jeśli posiadamy dynamicznie przyznawane IP, które zmienia się po każdym restarcie serwera. Do rozbudowy tego skryptu wrócimy w dalszej części publikacji. Zanim przejdziemy do konfiguracji programu zatrzymajmy się chwilę przy jego trzech trybach pracy, które pomogą nam zrozumieć dalsze ustawianie programu. Jak już wspomniałem PortSentry potrafi wykryć ataki typu stealth (ukryte), takie jak często spotykana technika skanów polegająca na wysyłaniu początkowego pakietu TCP-SYN, oczekiwaniu na pakiet TCP-ACK, który wskazuje, że w porcie nasłuchuje proces, i nie wysyłaniu trzeciego pakietu trójstopniowego uzgodnienia TCP (pakietu ACK). Nasz mały IDS może nasłuchiwać na portach TCP lub UDP w jednym z trzech trybów:

1). Podstawowy – tryb powiązania z portem (opcja -tcp lub -udp). PortSentry zwiąże się wtedy z portami wymienionymi na liście, będzie nasłuchiwał połączeń i odpowiednio reagował. Początkowe trójstopniowe uzgodnienie połączenia TCP będzie obsługiwane przez jądro Linuksa lub Uniksa jak to woli, więc ta metoda nie wykryje skanowania TCP typu: stealth i innych “niewidocznych” technik, takich jak skanowanie FIN, Null lub Xmas.

2). Tryb skanowania stealth (opcja -stcp lub -sudp). Program otworzy surowe gniazdo (raw socket) oraz będzie monitorował połączenia w trybie promiscuous (tak samo jak to robi sniffer) i uaktywniał się w razie ataku na port z określonych zakresów. Skanowanie typu stealth będzie wykrywane.

3). Zaawansowany tryb skanowania stealth (opcja -atcp lub -audp). Program podobnie jak w metodzie wyżej otworzy surowe gniazdo oraz będzie monitorował połączenia i uaktywniał się w razie ataku na każdy port z określonego zakresu, w którym nie nasłuchuje inny proces. Skanowanie typu stealth będzie oczywiście wykrywane. Zaawansowany tryb ma tę przewagę na opisanym wyżej, że wykrywa on próby odgadnięcia klienckich portów o wysokich numerach, które mogą być otwarte, w nadziei przejęcia istniejącego połączenia. Jest to bardzo czuły mechanizm zwłaszcza w razie podania szerokiego zakresu portów. Inną zaletą tego trybu jest, że intruzi będą widzieć port jako zamknięty lub odfiltrowany, a nie otwarty, jak w przypadku podstawowego trybu TCP. Jak opisano w skromnej dokumentacji programu na tryb zaawansowany istnieje możliwość przeprowadzenia ataku DoS, podając sfałszowany adres źródłowy. Jednak gdyby taka sytuacja zaistniała (jeśli nie prowadzimy dobrze znanej witryny, raczej nie ma powodu do obaw) – wystarczy ponownie uruchomić program.

  Większość administratorów za najodpowiedniejszy uzna zaawansowany tryb stealth, zarówno w wersji TCP, jak i UDP, ponieważ wykryje on ataki z pełnym połączeniem, SYN (półotwarte), FIN, XMASS, NULL i inne skany TCP, jak również wszystkie skany UDP z wyjątkiem małych fragmentów (dlatego nasz serwer lub firewall powinien być skonfigurowany tak, aby defragmentować wszystkie pakiety w celu uniknięcia ataków fragmentacyjnych – w jądrach < 2.4 należy wkompilować opcję CONFIG_IP_ALWAYS_DEFRAG, a w 2.4 przy starcie naszego systemu należy wykonać następujące polecenie – najlepiej dopisać je do skryptu startowego rc.local:
echo 1 > /proc/sys/net/ipv4/ip_always_defrag).

Po wyborze odpowiedniego poziomu nasłuchu możemy przejść do konfiguracji programu. W tym celu otwieramy plik portsentry.conf – nie jest to skrypt powłoki, ale obowiązują w nim podobne reguły, to znaczy wiersze zaczynające się od znaku # i wiersze puste są komentarzami, a znak = przypisuje zmiennej wartość w cudzysłowie. Teraz musimy określić, które porty TCP i UDP mają uaktywniać program i jakie czynności będą podejmowane. Choć plik jest dość dobrze opatrzony komentarzami, warto zauważyć, że PortSentry będzie używać tylko tych zmiennych, które odnoszą się do trybu ochrony wybranego za pomocą opcji wiersza poleceń. Plik zawiera wykomentowane, sugerowane wartości, od których możemy zacząć dostosowanie go do potrzeb swojej sieci. Niewykluczone, że będziemy musieli je zmienić, w zależności od usług oferowanych przez nasz system np. jeśli program będzie działał na zaporze sieciowej, prawdopodobnie będziemy udostępniali tylko SSH oraz Ident:

Tryb podstawowy i stealth:

# Use these if you just want to be aware:
TCP_PORTS="1,11,15,79,111,119,143,540,635,..."
UDP_PORTS="1,7,9,69,161,162,513,635,640,..."

Jeżeli chcemy używać trybu podstawowego trybu powiązania z portem, albo trybu skanowania stealth musimy odkomentować (usunąć znak #), z jednej z trzech powtarzających się wpisów TCP_PORTS oraz UDP_PORTS – każdy z nich tyczy się tych trybów, lecz autor programu postanowił ułatwić nam wybór dając określenia jak bardzo chcemy być przezorni: pierwsza para wpisów tyczy się prawdziwych paranoików (really anal), druga ludzi przezornych, a trzecia tych którzy coś podejrzewają. Oczywiście każdą z nich możemy poddać edycji (lecz tylko jedna para może być aktywna), a nawet musimy w celu upewnienia się, że chronione porty nie nakładają się z tymi, na których nasłuchują prawdziwe usługi. Lista podzielona jest przecinkami; spacje i znaki tabulacji są niedozwolone. Pamiętajmy, że jeśli wybieramy tryb podstawowy , liczba otwartych portów będzie ograniczona – w jądrach Linuksa 2.2 i 2.4 zwykle obowiązuje limit 1024 otwartych plików (w wielu systemach uniksowych limit ten wynosi 64 pliki na proces, łącznie z wszystkimi zwykłymi plikami oraz urządzeniami wejścia – wyjścia, które są otwarte). Dlatego też nie możemy przesadzić z listą portów. Podczas testów program świetnie sprawdzał się z aktywną drugą parą wpisów, która została dostosowana do usług serwera.

Tryb advanced stealth scan detection:

ADVANCED_PORTS_TCP="1500"
ADVANCED_PORTS_UDP="1024" 
---
# Default TCP ident and NetBIOS service
ADVANCED_EXCLUDE_TCP="22,113,138,135,139,445"
# Default UDP route (RIP), NetBIOS, bootp broadcasts.
ADVANCED_EXCLUDE_UDP="520,138,137,67"

Zmienna ADVANCED_PORTS – określa największy numer portu, który podlega monitorowaniu. W przeciwieństwie do trybu podstawowego tryb ten pozwala na monitorowanie zakresu nawet tysiąca portów, ponieważ nie wiąże się z poszczególnymi portów. Osobno ustawiamy wartości dla portów TCP (Transport Control Protocol) i UDP (User Datagram Protocol). Ponieważ Nmap skanuje zwykle jedynie około 1500 portów, zamiast standardowej wartości minimalnej 1024 dobrze jest ustawić 1500, jako najniższą (choć dokumentacja przestrzega przed monitorowaniem portów powyżej 1023 – podczas testów, nie zauważyliśmy żeby powodowało to problemy), a najwyższą 6010 – ponieważ wiele mało odpornych i często atakowanych usług używa portów o wyższych numerach (np. socks, nfs i X). Choć w tym trybie PortSentry domyślnie nie prowadzi nasłuchu na czynnych portach serwera, dzięki zmiennej ADVANCED_EXCLUDE wymieniamy porty, które mają być wyłączone z zakresu, ponieważ zamierzamy udostępniać w nich prawdziwe usługi albo ignorować przychodzący ruch do nich – powinny to być także numery portów, które są często używane przez pomyłkę, na przykład port 80 (HTTP) na serwerze, gdzie stoi tylko HTTPS (443). Często się zdarza, że różne hosty próbują się łączyć z zaporą na port 445 (microsoft-ds), ponieważ za firewallem stoją komputery używające systemu Windows.

Pliki konfiguracyjne:

# Hosts to ignore
IGNORE_FILE="/usr/local/psionic/portsentry/portsentry.ignore"
# Hosts that have been denied (running history)
HISTORY_FILE="/usr/local/psionic/portsentry/portsentry.history"
# Hosts that have been denied this session only (temporary until next restart)
BLOCKED_FILE="/usr/local/psionic/portsentry/portsentry.blocked"

Plik określony przez zmienną IGNORE_FILE wymienia hosty, których pakiety chcemy całkowicie ignorować, czyli z perspektywy blokowania intruzów są to hosty, którym w pełni ufasz, i które potrzebują dostępu przez naszą zaporę sieciową. Lista ta obejmuje lokalne interfejsy oraz może obejmować inne komputery administratora, jeśli są także dobrze zabezpieczone. Plik ten jest generowany automatycznie przez skrypt ignore.csh, który odczytuje aktualne adresy naszych interfejsów w serwerze. Skrypt ten szczególnie się przydaje jeśli niektóre spośród naszych interfejsów są dynamiczne. W celu zmuszenia skryptu, aby dodawał także zaufane numery IP np. z pliku trusted.hosts należy dodać wiersze:

if (-f /usr/local/psionic/portsentry/trusted.hosts) then
   cat /usr/local/psionic/portsentry/trusted.hosts >> $SENTRYDIR/$TMPFILE
endif

zaraz pod wierszem:

echo '0.0.0.0' >> $SENTRYDIR/$TMPFILE

W ten sposób po odpaleniu skryptu ignore.csh, nad pisze on plik portsentry.ignore i umieści w nim adresy IP interfejsów systemu oraz wymienione, zaufane systemy z pliku trusted.hosts (ostatnia linia pliku musi być pusta oraz należy pamiętać by nadać temu plikowi prawa 600). Jeśli nie chcemy korzystać ze skryptu to musimy w pliku portsentry.ignore samemu określić zaufane IP, które powinny być ignorowane. Możemy wymienić tutaj interfejsy systemu, w którym będzie działał program PortSentry, łącznie z adresem IP urządzenia pętli zwrotnej (loopback – lo), a także inne zaufane hosty. Od wersji 1.1 programu można także używać maski sieciowej, podając liczbę bitów identyfikujących sieć. Idąc dalej – plik określany przez zmienną HISTORY_FILE zawiera informacje o wszystkich wykrytych przez program atakach, natomiast BLOCKED_FILE jest ścieżką do pliku, w którym znajdują się aktualnie (w tej sesji programu do następnego restartu) zablokowane numery IP. O tych plikach szczególnie o portsentry.history należy pamiętać podczas rotacji logów serwera.

RESLOVE_HOST = "1"

   Zmienna ta zwykle ustawiona jest na wartość “1” (w cudzysłowie), aby program podejmował próbę odwzorowania nazwy atakującego nasz system. Dzięki temu możemy dowiedzieć się wiele więcej o okolicznościach przeprowadzanego ataku. Podczas testów programu okazało się, że polskie domeny bardzo są lubiane przez domeny .us (USA), .fi (Finlandia) oraz .it (Włochy). Dodatkowo jeśli nazwa hosta zaczyna się od wpisu typu “ns2” czy “dns2”, prawdopodobnie jest to czyjś serwer DNS, który został przejęty lub nie. Wiele intruzów przybiera strategie “dobrego administratora”, gdzie jako jedyni na swoim serwerze odbierają pocztę przeznaczoną dla konta root. W ten sposób, odbierając zażalenia na wpadkę danego użytkownika (którym w rzeczywistości sami są) odpisują, że użytkownik ten został usunięty z systemu lub jego konto zostało zablokowane na czas nieokreślony. Wtedy najlepiej od razu przekazać informacje, że w razie powtórnego incydentu zostanie powiadomiony jego ISP (Internet Service Provider) oraz organizacja CERT. Wracając do tematu – jeśli nasz serwer DNS (lub naszego ISP) działa wolno, ustawiamy tę zmienną na “0”.

Sposób reagowania programu na skanowanie:

# 0 = Do not block UDP/TCP scans.
# 1 = Block UDP/TCP scans.
# 2 = Run external command only (KILL_RUN_CMD)

BLOCK_UDP="1"
BLOCK_TCP="1" 

Zmienne te określają, czy program PortSentry będzie działał jako adaptacyjna zapora sieciowa, a jeśli tak to w jaki sposób. Używamy wartości “1“, aby sam blokował ruch za pomocą zmiennych KILL_ROUTE i / lub KILL_HOSTS_DENY oraz KILL_RUN_CMD, wartości “2“, aby przywołał tylko polecenie określone przez zmienną KILL_RUN_CMD (np. nasze własne reguły IP Tables / IP Chains, a nawet interfejs innej zapory), albo “0“, aby nie blokować ruchu, a używać programu w celach obserwacyjnych.

   Jeśli nadamy wartość “1”, zmienna KILL_ROUTE, KILL_HOSTS_DENY i KILL_RUN_CMD będzie określać, jak program powinien blokować napastnika. W Linuksie możemy wykorzystać moduły IP Tables, IP Chains, TCP Wrappers lub polecenie route. Wadą metody z poleceniem route jest to, że w przypadku kolejnych ataków otrzymamy komunikat “already blocked” (już zablokowano), z wyjątkiem podstawowego trybu TCP programu. Natomiast moduły iptables lub ipchains nie będą nam więcej zawracać głowy i nie przepuszczą kolejnych pakietów napastnika. W zależności od używanego filtra pakietów proponujemy podać następujące polecenia KILL_ROUTE, które umożliwia zlikwidowanie lokalnej trasy do winowajcy, który skanuje porty:

KILL_ROUTE="/sbin/ipchains -I input 1 -s $TARGET$ -j DENY"
KILL_ROUTE="/usr/sbin/iptables -I INPUT 1 -s $TARGET$ -j DROP"

Oczywiście wybieramy tylko jedną z tych opcji – w zależności czy posiadamy jądro 2.2 z ipchains czy 2.4 z iptables lub 2.4 z kompatybilnością używania ipchains. Jeśli chcemy dodatkowo poddać logowaniu blokowane pakiety wystarczy, że na końcu pierwszego wpisu (odwołując się do ipchains) dodamy dodatkowy parametr: “-l” (od -log). Jeśli chodzi o logowanie iptables to najlepiej jeśli przed uruchomieniem PortSentry stworzymy nowy łańcuch logujący:

iptables -N DROPl 2> /dev/null
iptables -A DROPl -j LOG --log-prefix 'DROPl: '
iptables -A DROPl -j DROP

Po dokonaniu tych wpisów w drugim wpisie (odwołując się to iptables) – końcówkę “-j DROP” zmieniamy na “-j DROPl“. Oczywiście możemy pominąć logowanie pakietów odrzuconych i po prostu wpisać jedną z dwóch powyższych linijek. Lecz warto zaznaczyć, że ocena techniki logowania dla użytkownika polega na możliwości określenia adresu i portu źródłowego oraz docelowego, a także na podstawie innych szczegółów możemy stwierdzić, dlaczego pakiet naprawdę został odrzucony. Po wykonaniu komendy przypisanej do KILL_ROUTE PortSentry przejdzie do wykonania zmiennej KILL_HOSTS_DENY (jeśli ta jest pozbawiona komentarza). Służy ona do definiowania wpisu /etc/hosts.deny, który program powinien umieścić w tym pliku w celu zablokowania hosta za pomocą narzędzia TCP Wrappers. Możemy traktować to jako zabezpieczenie, w wypadku, gdy łańcuchy ipchains lub iptables zostaną przez przypadek wyczyszczone (warto wspomnieć, że blokadzie będą poddawane tylko te połączenia do usług, które obsługują osłonę TCP Wrappers np. sshd lub inne w które została wkompilowana ta obsługa), lub zostanie przeprowadzony restart serwera – wtedy łańcuchy muszą zostać wpisane na nowo! Zalecamy ustawienie tej zmiennej w sposób zbliżony do następującego:

KILL_HOSTS_DENY="ALL: $TARGET$ : DENY"

   Ostatnią zmienną która zostanie wykonana jest KILL_RUN_CMD – zmienna ta służy do określania polecenia, którego PortSentry powinien użyć, przekazać powłoce jako wiersza poleceń tuż lub po wykonaniu polecenia zdefiniowanego w zmiennej KILL_ROUTE. O tym czy RUN_CMD będzie wykonana przed czy po KILL_ROUTE decyduje zmienna KILL_RUN_CMD_FIRST – ustawienie tej opcji na “0” wykona powyższą komendę zanim KILL_ROUTE wykona się, natomiast ustawienie wartości “1” wykona polecenie z RUN_CMD zaraz po KILL_ROUTE. Poniżej postaramy się omówić dwa przypadki gdzie można zastosować różne ustawienie zmiennej FIRST. Lecz przed tym należy wspomnieć, że czasami trzeba oprzeć się pokusie wykorzystania tego polecenia (chodzi o KILL_RUN_CMD), do podejmowania automatycznego procesu. Jeśli polecenie zawarte w tej zmiennej wymaga poświęceniu znacznej ilości czasu serwera, polecenie to może zostać wykorzystane jako próba ataku Denial of Service. Dlatego umieszczane tutaj komendy muszą zostać dobrze przemyślane.

Pierwszym przypadkiem będzie kiedy komenda ze zmiennej RUN_CMD będzie wykonana przed komendą ze zmiennej KILL_ROUTE. Przypadek ten jest rozpatrywany ze względu na brak trwałości wpisów iptables po ponownym uruchomieniu serwera. W większości instalacji nie ma powodu, żeby kiedykolwiek odblokowywać atakujący system – dlatego najlepiej utworzyć dodatkowy skrypt, który będzie powodował “zapamiętanie” wrogich hostów oraz ich zablokowanie. Poniżej są zamieszczone komendy, które powinny zostać użyte w tej zmiennej (w zależności czy korzystamy z iptables czy ipchains):

KILL_RUN_CMD="echo iptables - I INTPUT 1 -s $TARGET$ -j DROP >> /etc/rc.d/rc.portsentry.fw
KILL_RUN_CMD="echo ipchains -I input 1 -s $TARGET$ -j DENY >> /etc/rc.d/rc.d/rc.portsentry.fw

W ten sposób, jeśli użyjemy zmiennej KILL_RUN_CMD do wywołania odpowiedniego polecenia zablokujemy napastnika na stałe, ponieważ zaktualizowany zostanie plik /etc/rc.d/rc.portsentry.fw, który będzie stanowił swoistą bazę agresorów. Teraz tylko wystarczy na końcu pliku /etc/rc.d/rc.local dodać wywołanie tej bazy:

. /etc/rc.d/rc.portsentry.fw

Spowoduje to wczytanie reguł, które dotyczą zablokowanych na stałe systemów. Oczywiście oprócz zapisu do naszej bazy skazańców PortSentry będzie na bieżąco blokował skanujące nas hosty za pomocą wywołania KILL_ROUTE. Zalecamy, co jakiś czas monitoring pliku rc.portsentry.fw, w celu kontroli jego rozrostu, bo może się zdarzyć, że nasz system przy starcie będzie wykazywał proces zatrzymania – w celu uzupełnienia tabel firewalla o tysiąc pozycji – co określony czas możemy kasować odgórne elementy w celu odciążenia firewalla. Jak widzimy przedstawione rozwiązanie ma typowy charakter defensywy. Drugim rozwiązaniem, które uruchamia dodatkową komendę po poleceniu KILL_ROUTE, jest bardziej informacyjne, niż defensywne. Spowoduje ono wysłanie wiadomości e-mail do administratora, lub przez nas ustalonego użytkownika. W tym celu użyjemy następującego polecenia:

KILL_RUN_CMD="(sleep 2; echo Portsentry - Intruz: $TARGET$ Port: $PORT$ Tryb: $MODE$; echo ''; echo Logi: ; tail -20 /var/log/messages)|mail -s 'Raport Portsentry.' root abuse

Zamiast używać lewego ukośnika (backslash \) oznaczającego nową linię najlepiej jest umieścić powyższy wpis w pliku portsentry.conf jako jeden długi wiersz. Końcowe dwa słowa oznaczają nazwy kont, do których ma zostać przekazana informacja o wykryciu skanowania, a jako treść listu zostaną dołączone linijki (20) pliku z logami – dostarczające nam dokładniejszych informacji na temat zdarzenia (do wysyłania poczty przy pomocy polecenia mail musimy posiadać zainstalowany program lub występujący w dystrybucji Slackware pakiet nail). Te opcje zakańczają konfigurację sposobów reagowania programu.

Pozostałe opcje konfiguracyjne:

SCAN_TRIGGER="0"

Jeśli ta zmienna ma wartość większą od “0”, skanujący porty może wykonać pewną liczbę skanów (z zakresu 1 do 2), bez ponoszenia żadnych konsekwencji. Optymalną wartością wydaje się liczba 1 (szczególnie w sytuacjach, gdy host pełni funkcję routera / firewalla chroniąc odmienne systemy), dzięki czemu przypadkowy skan portów (taki, który jest odnotowany z flagą TCP SYN) nie spowoduje żadnej reakcji. Lecz tutaj należy się także zastanowić nad faktem, że intruz może poświęcić dłuższy czas na wywiad systemu poprzez żądania od skanera sprawdzania pojedynczych portów, co określony czas (jeden na dzień), co w przypadku wartości “1” tej zmiennej może zostać w ogóle niezauważone. Lepszym rozwiązaniem wydaje się przetestowanie programu oraz określenie jakie najczęściej porty padają ofiarą przypadkowych prób nawiązań łączności. Wartość “2” powoduje większą ignorancję programu (do dwóch “przypadkowych” skanowań).

PORT_BANNER="*** YOUR CONNECTION ATTEMPT HAS BEEN LOGGED. FSCK OFF ***"

Opcja ta powoduje wyświetlenie danego tekstu podczas próby połączenia się na “pusty” port, który podlega PortSentry. Tekst ten jest tylko wyświetlany w przypadku, gdy program pracuje w normalnym trybie – podczas trybów wykrywania ukrytego skanowania nie będzie wyświetlana żadna wiadomość tekstowa.

  Po konfiguracji PortSentry w końcu przyszedł czas na jego aranżacje. Wywołanie programu będzie polegało na dodaniu poniżej zaprezentowanych wierszy do pliku demona: /etc/rc.d/rc.local. Wpisy te spowodują także zakończenie i wznowienie programu, co ułatwia użycie go w razie modyfikacji jego pliku konfiguracji – portsentry.conf:

echo "Uruchamiam PortSentry w trybie zaawansowanym."
killall portsentry
/usr/local/psionic/portsentry/portsentry/ignore.csh
/usr/local/psionic/portsentry/portsentry -atcp
/usr/local/psionic/portsentry/portsentry -audp

Dla osób, które uwielbiają posiadać do wszystkich programów osobne demony pozwalające na szybką kontrolę nad ich pracą – poniżej zamieszczamy mały skrypt, który pozwala na start oraz zatrzymanie PortSentry. Skrypt nazywa się rc.portsentry – należy umieścić go razem z innymi demonami w katalogu /etc/rc.d:

#!/bin/sh

case "$1" in
'start')
/usr/local/psionic/portsentry/ignore.csh
/usr/local/psionic/portsentry/portsentry -atcp
;;
'stop')
killall portsentry
;;
*)
echo "Użycie: $0 { start | stop }"
;;
esac
exit 0

Jeśli zdecydujemy się na używanie powyższego demona wystarczy zastąpić pojedyncze wpisy w rc.local na:

if [ -x /etc/rc.d/rc.portsentry ]; then
   /etc/rc.d/rc.portsentry start
fi

  Oczywiście wiersze wywoławcze należy dostosować do własnych preferencji – np. pominąć skrypt dodający lokalne interfejsy, ponieważ sami pragniemy wpisać zaufane adresy, czy uruchomić program w innym trybie detekcji skanowania. Warto wspomnieć, że na serwerach, które nie korzystają z usług za pośrednictwem protokołu UDP można pominąć wykrywanie skanerów UDP. W ten sposób odciążamy system mając pewność, że agresor nie uzyska strategicznych informacji. Na maszynie, na której były przeprowadzane testy nad programem nie nasłuchują żadne usługi korzystające z protokołu UDP (pomijając wymianę danych z serwerami DNS lokalnego ISP na porcie 53 – lecz do portu tego dopuszczane są tylko numery IP serwerów DNS ISP) dlatego uruchomienie programu z obsługą protokołu UDP po wstępnym czasie testów zostało porzucone. Po pierwszym uruchomieniu programu najlepiej upewnić się, co do jego stanu poleceniem: tail -20 /var/log/messages. Następnie powinnyśmy przetestować konfigurację poprzez połączenie się z chronionym portem z niezaufanego systemu. Po tym fakcie należy sprawdzić, czy w pliku /var/log/messages (jeśli atak rejestrowany jest bezpośrednio przez syslog) pojawił się nowy wpis, w następującym formacie:

Feb 22 00:27:29 narfx86 portsentry[217]: attackalert: TCP SYN/Normal scan \
from host: ZB168188.ppp.dion.ne.jp/219.125.168.188 to TCP port: 23
Feb 22 00:27:29 narfx86 portsentry[217]: attackalert: Host 219.125.168.188 \
has been blocked via dropped route using command: "/usr/sbin/iptables -I \
INPUT 1 -s 219.125.168.188 -j DROP" 
Feb 22 01:12:45 narfx86 portsentry[217]: attackalert: Host 188.ppp.dion.ne.jp \
/219.125.168.188 is already blocked Ignoring

W tym przykładzie aplikacja została uruchomiona z parametrem: -atcp i miała obserwować wszystkie połączenia przychodzące TCP poniżej portu 1500. Napastnik (219.125.168.188) próbował połączyć się z portem 23 (telnet), z którym nie był związany żaden z demonów. Spowodowało to reakcję ze strony PortSentry, który umieścił odpowiedni wpis w firewallu w celu zablokowania kontaktu z podejrzanym hostem. Niecałą godzinę później intruz podejmuje drugą próbę skanowanie, ale tym razem PortSentry nie wpisuje nic w tablice iptables, ponieważ komputer ten jest już zablokowany. W celu sprawdzenia ilości wpisów dokonanych przez iptables wystarczy wydać polecenie: iptables -L INPUT -n -v | more. Zalecamy także wstępną obserwację nad programem w celu jego optymalnego dostosowania do charakterystyki serwera. Pomoże nam to także uniknąć fałszywych alarmów ze strony PortSentry.
Bonus:Porty od 1 do 20 kontroluje się, aby można było zablokować maszynę agresora, nim ta zdąży dojść do portów krytycznych (programy skanujące często sprawdzają porty kolejno, poczynając od pierwszego). Porty 20 – 500 są często podglądane ze względu na usługi pracujące w tym zakresie (tftp, snmp, smb) oraz 500 – 1024 są skojarzone z usługami, które często bywają przedmiotem zainteresowania intruzów (rsh, rlogin, rexec, mountd) – niektóre spośród nich mogą być użyte przez osoby atakujące do zdobycia zdalnej kontroli nad maszyną. Porty od 1024 do 32 768 obsługują liczne usługi, takie jak X Window, serwery IRC czy porty szeregowe routera – w tym zakresie najwięcej problemów można mieć z NFS. Jeżeli nie wiemy, co kryje się za konkretnym numerem portu, powinniśmy sprawdzić w /etc/services, jakie usługi skojarzone są z poszczególnymi portami, a następnie zebrać więcej informacji na temat danej usługi. Od czasu do czasu dobrze także wydać polecenie: netstat -tap, które wyświetli nam listę aktywnych połączeń internetowych. Należy także pamiętać, że skanowanie portów to jeszcze nie włamanie. To drugie jest karalne, to pierwsze – dozwolone, przynajmniej dopóki nie zacznie zakłócać pracy systemu, na przykład poprzez przeciążenie go (więcej informacji na ten temat możemy przeczytać w artykule pt. “prawa nowych technologii”). Ponawiające się próby skanowania naszych portów nie zawsze także oznaczają, że ktoś się na nas nastawił wrogo. Często bezmyślni posługiwacze eksploitów ustawiają skanery na jakąś klasę adresów i sprawdzają je na okrągło.

  Powiedzmy, że naszła nas fantazja i chcemy zmienić ustawienie logowania PortSentry do osobnego pliku. W tym celu, jeszcze przed instalacją przeprowadzamy edycję pliku portsentry_config.h oraz zmieniamy ustawienie SYSLOG_FACILITY z LOG_DAEMON na – dajmy na to – LOG_LOCAL0 tak, że po modyfikacji wpis będzie wyglądał następująco:

#define SYSLOG_FACILITY LOG_LOCAL0

Po czym odpowiednio modyfikujemy plik /etc/syslog.conf umieszczając w nim wpis:

local0.*			-/var/log/portsentry

Po tych modyfikacjach kompilujemy program oraz przeprowadzamy ponowne wczytanie konfiguracji demona syslog za pomocą polecenia: kill -HUP syslogd. W ten sposób spowodujemy, że wszystkie zdarzenia związane z PortSentry będą logowane do osobnego pliku. Dzięki temu rozwiązaniu będziemy mieli dostęp do rodzajowych informacji na temat działania programu, co także ułatwi przegląd aktywności ataków.

A co z firewallem?

Jeśli nasz firewall blokuje wszystkie porty oprócz portów aktywnych na serwerze, na których nasłuchują dane usługi np. na serwerze uruchomione są usługi: WWW (port 80) oraz POCZTA (port 25) – a reszta ruchu sieciowego jest blokowana poprzez regułę iptables: DROP, w tym przypadku należy odłonić przynajmniej (w zależności od ustawienia zmiennej SCAN_TRIGGER) po dwa “puste” porty, na których nie będzie nasłuchiwać żadna usługa. W naszym przypadku będą to 77, 79 oraz 22, 23. W ten sposób host skanujący od początkowego zakresu portów zostanie wyłapany i zablokowany na specjalnie otwartych do tego celu portach. Ustawienia “lipnych” portów mogą być różne – możemy pokusić się o otwarcie dwóch portów przed usługą, dwóch portów po usłudze czy nawet losowych przedziałów na przestrzeni całego zakresu.

Więcej informacji: sentrytools, README.COMPAT & stealth, man nail, nmap

Kategorie K a t e g o r i e : Bezpieczeństwo

Tagi T a g i : , , , ,

Komentowanie tego wpisu jest zablokowane.