Generator pakietów scapy

23 kwietnia 2013, 09:43 | Narzędzia | 0 komentarzy
: zin o bezpieczeństwie - pobierz w pdf/epub/mobi.

Czy istnieje łatwy sposób na wygenerowanie niemal dowolnych pakietów? Czy można bez większych trudności zmodyfikować przechwycony pakiet i wysłać go ponownie? Czy nieskomplikowanym zadaniem jest przygotowanie fuzzera protokołu sieciowego?

Na te wszystkie pytania możemy odpowiedzieć: tak – mając do dyspozycji darmowe oprogramowanie scapy. Jedną możliwości oferowanych przez to narzędzie jest generowanie pakietów – przy czym, w odróżnieniu od innych znanych generatorów pakietów (takich jak: sendip, nemesis, netdude, czy hping), scapy:

  • posiada bardzo dużą bazę obsługiwanych protokołów,
  • jest prosty i szybki w obsłudze,
  • zapewnia użytkownikowi wysoką elastyczność podczas korzystania z oferowanej przez siebie funkcjonalności,
  • jest aktywnie rozwijany,
  • oferuje bardzo szerokie możliwości skryptowania,
  • zapewnia relatywnie proste możliwości implementacji obsługi zupełnie nowego rodzaju pakietów i protokołów (wymagana jest przy tym jednak znajomość języka python).

Sam autor narzędzia twierdzi, że jest ono w stanie zastąpić takie aplikacje jak: hping, 85% funkcjonalności nmap-a, arpspoof, arp-sk, arping, tcpdump, tethereal czy p0f. Nie będziemy polemizować z tym twierdzeniem –  zaprezentujemy za to praktyczne przykłady wykorzystania scapy, niech one same będą komentarzem do możliwości tego oprogramowania.

ls() – wyświetlenie obsługiwanych pakietów

Scapy w wersji 2.1.0 obsługuje przeszło 300 rodzajów pakietów, przy czym pakiet rozumiemy tutaj bardzo ogólnie – jako pewien odpowiednio sformatowany zbiór danych, który może być przesyłany przez sieć (stosowne formatowanie określa odpowiedni protokół sieciowy). Na listingu poniżej prezentujemy niewielki fragment listy pakietów zaimplementowanych w scapy, przy czym dostępne są dodatkowe pluginy uzupełniające tą listę (przykład – protokół routingu OSPF):

ls() – wyświetlenie szczegółów budowy pakietu

Przed utworzeniem pakietu w scapy warto zapoznać się z jego strukturą:

W pierwszej kolumnie podawana jest nazwa każdego pola, w drugiej jego typ, a w trzeciej – wartość domyślna przy tworzeniu nowego pakietu.

Tworzenie nowego pakietu

W scapy jest to prosta operacja:

Wyświetlenie szczegółów pakietu

W przykładzie powyżej jako domyślny typ ICMP został ustawiony ‚echo-request’ (znany z popularnego ping-a). Jeśli przy budowie pakietu chcielibyśmy podać inny typ, możemy zrobić to w sposób następujący:

Skorzystaliśmy więc z podania kodu bezpośrednio lub za pośrednictwem mnemonika. Mnemoniki dla pól typu enum możemy wyświetlić za pomocą składni: protokół.nazwa_pola.i2s

Łączenie pakietów

Jak wiemy, pełen prawidłowy pakiet ICMP, składa się z kilku warstw: ramka (na potrzebny artykułu nazywamy ją „pakietem”) warstwy drugiej modelu OSI, pakiet IP oraz pakiet ICMP. Złóżmy dwa pakiety – IP oraz wcześniej stworzony ICMP. Ramka ethernetowa zostanie dodana później – już przez scapy.

Zauważmy, że wszystkie pola zostały wypełnione zgodnie z wartościami domyślnymi (polecenie ls(typ_pakietu)) – a dodatkowo pole IP.proto zostało wypełnione poprawnie – tj. pakiet protokołu IP w powyższym pakiecie transportuje pakiet protokółu ICMP. Zwróćmy również uwagę na pola chksum – przyjęły one wartość None. W tym przypadku oznacza to, że sumy kontrolne zostaną wyliczone na podstawie tego jak zbudujemy pakiet – a wykona to za nas scapy. Aktualną sumę kontrolną można zobaczyć wykorzystując metodę show2():

Przy okazji wspomnijmy, że dostępne w danej klasie zmienne i metody możemy uzyskać poleceniem dir (wynik tego polecania poniżej, został skrócony w celu ułatwienia prezentacji wyników):

Z kolei pomoc dotyczącą interesującej nas metody możemy uzyskać poleceniem help():

Modyfikacja zawartości pakietu

Aby zmodyfikować pole w interesującej nas warstwie, stosujemy notację: pakiet[warstwa].pole = wartość. Na przykład:

Wysłanie pakietu oraz odebranie odpowiedzi

Istnieje kilka funkcji wysyłających oraz odbierających pakiety –  można je poznać wydając polecenie lsc() oraz help(nazwa_funkcji). W przykładzie poniżej wykorzystamy funkcję sr1(), która wysyła pakiety w warstwie 3 modelu OSI  (tj. ramka warstwy drugiej zostanie za nas uzupełniona) oraz odbiera pierwszy pakiet odpowiedzi.

Zauważmy, że nie musieliśmy uzupełniać pakietu o ramkę ethernetową, tę pracę wykonała za nas funkcja sr1(). Jeśli chcielibyśmy jednak kontrolować dane również w warstwie 2, musielibyśmy skorzystać z funkcji srp1() oraz uzupełnić pakiet o ramkę Ethernet. Przy założeniu, że w zmiennej i zdefiniowany mamy pakiet IP()/ICMP(), dołożenie ramki ethernetowej wygląda następująco:

Dla dalszego zobrazowania możliwości oferowanych przez scapy, prezentujemy wynik wspomnianego wyżej polecenia lsc():

Wygenerowanie grupy pakietów

Spróbujmy tym razem wygenerować nie jeden pakiet – a całą ich grupę, mianowicie 18 pakietów ICMP o polu type przyjmującym wartości od 0 do 18 (pozostałe pola przyjmą wartości domyślne ustalone w scapy). Tym razem skorzystamy z funkcji sr() (jej nazwa to skrót od send-receive), wysyłającej w warstwie 3. Funkcja ta zwraca dwie wartości: pakiety z wysyłanego zbioru, które doczekały się odpowiedzi oraz te na które odpowiedź nie przyszła.:

 Proste skanowanie portów

Wykorzystując wiedzę z powyższego przykładu wykonajmy prosty skaner portów. W naszym przypadku będzie to wysłanie 4 pakietów TCP z ustawioną flagą Syn, na cztery różne porty:

W pętli powyżej przeglądamy całą zwróconą tablicę o nazwie a. Każdy element tej tablicy posiada dwa kolejne elementy – pakiet wysłany, oraz otrzymana na niego odpowiedź (w pętli odpowiadają tym elementom zmienne req oraz resp). Jeśli odpowiedź jest pakietem TCP z flagą SA, oznacza to że badany port jest otwarty (otrzymaliśmy segment TCP z flagami SA w odpowiedzi na segment z flagą S).

Podsłuchiwanie ruchu oraz modyfikacja komunikacji sieciowej

Aby podsłuchać ruch, możemy skorzystać z wbudowanej w scapy funkcji sniff(), możemy również wczytać zbiór pakietów w formacie libpcap  – funkcja rdpcap()

Zauważmy, że przechwycony przez nas pakiet IP zawiera początkowo poprawną sumę kontrolną, jednak po zmianie docelowego adresu IP, suma kontrolna będzie błędna! Dlatego aby wysłać pakiet bez błędów poprosiliśmy scapy o automatyczne wygenerowanie prawidłowej sumy za nas, podstawiając jej wartość na pustą:

Odczytanie podsłuchanych pakietów ze zrzutu w formacie libpcap jest równie proste:

Przy okazji warto również wspomnieć o funkcji wrpcap() – zapisującej pakiety w formacie libpcap. Taka możliwość może okazać się przydatna, jeśli chcielibyśmy wybrane pakiety poddać obróbce lub analizie w innym, zewnętrznym narzędziu. Poniżej prezentujemy przykład sfragmentowania komunikacji IP, z wykorzystaniem narzędzia tcprewrite, które posiada wkompilowaną obsługę mechanizmu fragroute:

Fuzzing protokołów sieciowych

W skrócie, fuzzing protokołów sieciowych, polega na wygenerowaniu pakietów nie koniecznie zgodnych ze specyfikacją protokołu oraz  sprawdzeniu w jaki sposób na taką komunikację zareaguje docelowy system. Przykładowo, niepoprawnym pakietem może być pakiet IP z ustaloną nietypową wartością w polu IP.version. Często w ten sposób wykryta może być błędna obsługa danego pakietu przez docelowy system, co niekiedy kończy się jego kompromitacją (patrz np. pracę Wifi Advanced Fuzzing @ Blackhat EU 07, pokazującą podatności umożliwiające wykonanie wrogiego kodu na bezprzewodowym punkcie dostępowym z uprawnieniami jądra systemu operacyjnego – potencjalnie nawet bez konieczności uwierzytelnienia się w urządzeniu access point!). Najprostsza postać realizacji fuzzingu w scapy wygląda następująco:

Odpowiadający takiej komunikacji, zrzut wykonany przy pomocy tcpdump-a wygląda z kolei tak:

Analogicznie do przykładu wyżej, istnieje możliwość ręcznego podstawienia danego pola, nie wartością, a funkcją, zwracającą wartość losową:

Prosty program w pythonie

Jako ilustrację do możliwości skryptowania z wykorzystaniem scapy, przedstawiamy szkic bardzo prostego skanera portów napisanego w pythonie. Komentarzem do skryptu niech będzie sam kod źródłowy:

scapy-scanner.py (uruchomienie: python scapy-scanner.py):

Podsumowanie

Dociekliwych czytelników zachęcamy do własnego eksperymentowania z oprogramowaniem scapy. Mamy nadzieję, że pokazaliśmy moc tego narzędzia, którego rozmaite zastosowania są ograniczone niemal tylko pomysłowością użytkownika :-)

Jednocześnie zapraszamy na nasze szkolenie bezpieczeństwa sieci i testów penetracyjnych, gdzie w ramach kilku ćwiczeń pokazujemy wykorzystanie tego potężnego narzędzia.

Dodatkowe informacje

–michal.sajdak<at>sekurak.pl

Spodobał Ci się wpis? Podziel się nim ze znajomymi:



Komentarze

Odpowiedz