Aus Linux-Magazin 05/2024

Socat – Netcat auf Steroiden

© wklzzz / 123RF.com

Netcat gilt als Schweizer Netzwerk-Taschenmesser für den Admin. Socat geht noch weiter und beherrscht Multiplexing, TLS-gesicherte Kanäle, Pipes, Unix-Sockets und Executables.

Netcat ist zweifellos ein nützliches Werkzeug zum Testen von TCP-Verbindungen oder UDP-Ports, zum Übertragen von Dateien und vielem mehr [1]. Socat [2] geht noch weiter: Es beherrscht neben rohen TCP- und UDP-Verbindungen TLS-gesicherte Kanäle und greift auf Pipes, Unix-Sockets und Executables zu. Damit nicht genug, funktioniert außerdem das Multiplexing mehrerer Client-Verbindungen.

Genau wie Netcat nimmt Socat zwei Positionsparameter entgegen, um eine Verbindung zwischen zwei Netzwerkadressen herzustellen: »socat Adresse1 Adresse2«. Manchmal ist es durchaus sinnvoll, Dateien über Raw-TCP-Verbindungen zu übertragen, beispielsweise wenn Sie auf dem Zielsystem mit einem anderen User arbeiten müssen als auf der Quelle. Auf vielen Systemen, die ich betreue, ist das I/O-Logging von Sudo aktiv.

Das bedeutet, dass bei SCP- oder SFTP-Transfers mit User-Wechsel (Listing 1) die komplette Übertragung als Stdin und Stdout in die Sudo-Logs wandert. Unter Umständen sprechen wir dann von mehreren GByte, die im Verzeichnis »/var/log/sudo/« Platz finden müssen. Wer also nicht auf zusätzliche Sicherheit über Public-Key-Authentifizierung und deaktivierte Root-Konten verzichten möchte, muss sich für solche Übertragungen etwas Schlaues einfallen lassen. Hier kommen Netcat und Socat ins Spiel.

Listing 1

SFTP-Transfer mit User-Wechsel

$ sftp -s "sudo -u www-data /usr/lib/openssh/sftp-server" target.host

Mit Netcat lassen sich seit jeher Daten von Node A nach Node B transferieren (Abbildung 1), beispielsweise über Ein- und Ausgabeumleitungen. Dazu starte ich zunächst auf Node B Netcat im Listening-Modus (Listing 2, erste Zeile). Anschließend übertrage ich von Node A Inhalte an die Ziel-IP. Im gezeigten Beispiel erhält Netcat per Eingabeumleitung (»<«) die lokale Message-of-the-Day-Datei (zweite Zeile). Auf der Server-Seite wird sie dann per Ausgabeumleitung (»>«) in die Datei »output.txt« geschrieben.

Abbildung 1: F&uuml;r den Aufbau des Testnetzwerks gen&uuml;gen zwei Knoten.

Abbildung 1: Für den Aufbau des Testnetzwerks genügen zwei Knoten.

Zum Übertragen mehrerer Dateien greife ich auf Tar zurück. Das Urgestein nimmt Daten von der Standardeingabe entgegen und schreibt sie auf die Standardausgabe. Der Transfer mehrerer Dateien funktioniert auf diesem Weg analog. Auf Node B starte ich wieder Netcat im Listening-Modus und schicke die Standardausgabe per Pipe an Tar (dritte Zeile). Auf Node A sende ich die entsprechenden Dateien durch Tar per Pipe an Netcat (letzte Zeile).

Listing 2

Transfer per Netcat

tre@raspi02:~$ nc -l -p 9876 > output.txt
tre@raspi01:~$ nc raspi02:*9876 < /etc/motd
tre@raspi02:~$ nc -l -p 9876 | tar -xf -
tre@raspi01:~$ tar -cf -- Datei1 Datei2 ... DateiN | nc raspi02:*9876

Das bewerkstelligen Sie analog mit Socat und Tar, indem Sie auf Node B Socat auf Port 9876 lauschen lassen und die entsprechende Ausgabe durch Tar leiten (Listing 3, erste Zeile). Auf Node A übergeben Sie die Ausgabe von Tar an Socat (zweite Zeile). Im Beispiel kommen die Flags »reuseaddr« und »fork« zum Einsatz. Ersteres ermöglicht, dass Sockets selbst dann Verbindungen zu diesem Port aufbauen können, wenn er (teilweise) schon in Verwendung ist. Hingegen sorgt »fork« dafür, dass Socat Verbindungen an einen Kindprozess delegiert und somit direkt weiter lauschen kann.

Listing 3

Socat und Tar

tre@raspi02:~$ socat TCP-LISTEN:9876.reuseaddr,fork EXEC:"tar -xf -"
tre@raspi01:~$ socat EXEC:"tar -cf -- Datei1 Datei2 ... DateiN" TCP:raspi02:9876

Bind Shell

Hinter einer Bind Shell steckt das Szenario, dass Sie auf dem Ziel-Host eine Shell zum Beispiel per Netcat an einen TCP-Port binden. Sie können sie dann vom Quell-Host aus über den passenden Port kontaktieren – vorausgesetzt, es steht keine die Kommunikation verbietende Firewall im Weg und der Ziel-Socket ist zu erreichen.

Mit Netcat bauen Sie ein Bind Shell-Szenario mithilfe weniger Kommandos relativ flott auf. Auf Node B starten Sie wieder Netcat im Listening-Modus auf Port 9876 und geben die Standardausgabe per Pipe an eine Shell weiter (Listing 4, erste Zeile). Auf Node A müssen Sie nur noch eine TCP-Verbindung per Netcat zum Ziel-Host herstellen (zweite Zeile). Sobald das erledigt ist, können Sie von Node A aus Node B fernsteuern, selbst wenn es keine SSH-Verbindung oder Ähnliches gibt.

Listing 4

Bind Shell mit Netcat

tre@raspi02:~$ nc -lvp 9876 | /bin/bash
tre@raspi01:~$ nc -nv raspi02:*9876

Selbstredend empfiehlt sich das ausschließlich in sicheren Umgebungen, da Netcat nichts anderes tut, als eine Raw-TCP-Verbindung herzustellen. Zu den typischen Anwendungsfällen für eine solche Bind Shell gehört es, mit zwei Servern zu arbeiten, die sich zwar beide via SSH (per Public Key) erreichen lassen, bei denen aber das SSH-Agent-Forwarding deaktiviert ist. Hier lässt sich nicht von Node A nach Node B springen, weil sich der Private Key nicht auf Node A befindet: Das Konstrukt scheitert an der Authentifizierung.

Eine Bind Shell setzen Sie mit Socat ebenso schnell auf wie mit Netcat. Wie zuvor beginnen Sie auch hier auf dem Ziel-Host und starten Socat mithilfe des Befehls aus der ersten Zeile von Listing 5. Mit Socat benötigen Sie keine Pipe zu einer Shell. Stattdessen nutzen Sie schlicht das Protokoll »EXEC«. Im nächsten Schritt bauen Sie die Verbindung auf dem Quell-Host auf (zweite Zeile). Der Dash »-« steht wie gewohnt für die Standardeingabe Stdin – es ist also genauso korrekt, das Kommando wie in der dritten Zeile von Listing 5 zu schreiben. Dasselbe gilt für Stdout.

Listing 5

Bind Shell mit Socat

tre@raspi02:~$ socat -d -d TCP4-LISTEN:9876 EXEC:/bin/bash
tre@raspi01:~$ socat - TCP4:raspi02:9876
tre@raspi01:~$ socat STDIN TCP4:raspi02:9876

Reverse Shells

Wer jetzt darauf hofft, dass ich zeige, wie man über arglistige Office-Dokumente oder sonstige E-Mail-Anhänge ein Opfer mithilfe einer Reverse Shell fernsteuert, den muss ich enttäuschen. Wer konkrete Anleitungen zum Hacken von Fremdsystemen sucht, findet sie im Netz. Mir geht es hier ausschließlich um nützliche Tools und Verfahren für den Alltag mit Linux.

Reverse Shells sind, wie der Name bereits vermuten lässt, das Gegenstück zu Bind Shells. Das bedeutet, dass nicht auf dem Zielrechner, sondern auf der Quellmaschine eine Shell auf einem Port lauscht, zu der irgendwann der Ziel-Host eine Verbindung aufbaut. Was zunächst merkwürdig oder unlogisch klingen mag, ergibt dann Sinn, wenn es eben nicht ohne Weiteres möglich ist, von außen eine Verbindung in ein Firmennetz zu öffnen, ohne dabei auf wohldefinierte VPN-Methoden zurückzugreifen. Typischerweise sind Firewalls wesentlich durchlässiger, wenn man ausgehende Verbindungen aufbaut. Hier setzt eine Reverse Shell an, etwa, um sich über den Fortschritt eines langwierigen Prozesses benachrichtigen zu lassen.

Um eine Reverse Shell mit Socat aufzusetzen, beginne ich auf »raspi01«. Der Befehl aus der ersten Zeile von Listing 6 startet einen TCP-Listener auf Port 9876 und verwendet als Ziel die Standardausgabe (Abbildung 2). Nun kann ich vom Ziel-Host aus die Verbindung öffnen (zweite Zeile). Damit lassen sich vom Terminal auf »raspi01« aus, ähnlich wie per SSH oder Telnet, Kommandos auf der Zielmaschine »raspi02« ausführen (Abbildung 3). Lediglich die Richtung des Verbindungsaufbaus hat sich umgedreht.

Listing 6

Reverse Shell

tre@raspi01:~$ socat -d -d TCP4-LISTEN:9876 STDOUT
tre@raspi02:~$ socat TCP4:raspi01:9876 EXEC:/bin/bash
Abbildung 2: Das Aufsetzen der Reverse Shell erfolgt auf Node&nbsp;A.

Abbildung 2: Das Aufsetzen der Reverse Shell erfolgt auf Node A.

Abbildung 3: Nach dem Verbindungsaufbau lassen sich Kommandos auf Node&nbsp;B ausf&uuml;hren.

Abbildung 3: Nach dem Verbindungsaufbau lassen sich Kommandos auf Node B ausführen.

Zu Recht fragen sich Leser mit Security-Hintergrund nun, wo denn bitte bei Socat der Bonus liegt – bislang habe ich tatsächlich nur Altbekanntes vorgestellt. Doch das Ende der Fahnenstange ist noch lange nicht erreicht, denn Socat kann noch viel mehr.

Verschlüsselt

Möchten Sie Ad-hoc-Verbindungen in nicht vertrauenswürdigen Netzen verwenden, tun Sie das besser verschlüsselt. Dabei kommen Socats OpenSSL-Fähigkeiten ins Spiel. Als Voraussetzung für eine solche Verbindung benötigen Sie zwangsläufig ein TLS-Zertifikat, das aber ganz pragmatisch selbst signiert sein darf. Es dient wohlgemerkt in den hier besprochenen Konstellationen lediglich der Verschlüsselung und der Integrität der Daten. Authentizität lässt sich nicht gewährleisten, da es keinerlei Authentifizierungsmechanismus gibt. Richten Sie also über das Internet zu erreichende Bind Shells oder Reverse Shells ein, müssen Sie damit rechnen, dass sich womöglich unerwünschte Besucher einfinden.

Für eine OpenSSL-Verbindung erzeuge ich zunächst das Zertifikat (Listing 7, erste Zeile). Danach starte ich auf »raspi01« Socat im »OPENSSL«-Modus mit Reverse Shell (zweite Zeile) und docke von »raspi02« aus an diese Shell an (letzte Zeile, Abbildung 4).

Abbildung 4: Der OpenSSL-Verbindungsaufbau erfolgt von Node&nbsp;B aus.

Abbildung 4: Der OpenSSL-Verbindungsaufbau erfolgt von Node B aus.

Listing 7

OpenSSL-Verbindung

tre@raspi01:~$ openssl req -x509 -newkey rsa:4096
 -sha256 -days 3650 -nodes -keyout raspi01.key -out raspi01.crt -subj "/CN=raspi01" -addext "subjectAltName=DNS:raspi01"
tre@raspi01:~$ socat OPENSSL-LISTEN:9876,cert=raspi01.pem,verify=0,reuseaddr,fork STDOUT
tre@raspi02:~$ socat OPENSSL-CONNECT:raspi01:9876,cert=raspi01.pem,verify=0,cafile=raspi01.crt EXEC:/bin/bash

Legacy-Anwendungen

Es gibt sie in vielen Unternehmen: antiquierte Applikationen, die sich über unverschlüsselte Verbindungen wie Telnet erreichen lassen und daher sinnvollerweise lediglich auf dem Loopback-Interface lauschen, also lokal. Es kommt durchaus vor, dass Sie die Tools auf einem entfernten Host benötigen. Eine Möglichkeit dazu bestünde darin, das entsprechende Werkzeug so zu konfigurieren, dass es am externen Interface lauscht und damit für alle im Netz sichtbar ist.

Socat hilft dabei, das Problem zu lösen, indem es einen Tunnel vor die Legacy-Anwendung flanscht. Angenommen, das Tool lauscht auf Node A am lokalen Interface 127.0.0.1 auf Port 8877. Es lässt sich auf dem Host per Telnet ansprechen, nicht aber von einem anderen Teilnehmer im Netzwerk. Ich bringe Socat über das Kommando aus der ersten Zeile in Listing 8 dazu, selbst einen TLS-Listener auf Port 9988 zu starten, und verbinde als Ziel die Legacy-Anwendung. Dadurch kann ich auf Node B per Socat die Standardeingabe via TLS-Tunnel an Node A übermitteln (zweite Zeile).

Listing 8

TLS-Listener

tre@raspi01:~$ socat OPENSSL-LISTEN:9988,cert=raspi01.pem,verify=0,reuseaddr,fork TCP4:127.0.0.1:9988
tre@raspi02:~$ socat STDIN OPENSSL-CONNECT:raspi01:9988,cert=raspi01.pem,verify=0,cafile=raspi01.crt

Fazit

Als überaus mächtiges Tool läuft Socat dem Oldie Netcat eindeutig den Rang ab. Die hier angesprochenen Features zeigen lediglich einen kleinen Ausschnitt der Fähigkeiten des Werkzeugs. So können nicht nur TCP, File-Deskriptoren wie »STDIN« und »STDOUT« sowie OpenSSL-Sockets und Dateien als Adresstypen dienen, sondern auch Raw-Interfaces, Pipes oder Pseudo-Terminals (PTYs). Die Möglichkeiten, die Socat dabei eröffnet, fallen viel zu mannigfaltig aus, um sie hier aufzuführen. Es lohnt sich also unbedingt, die Manpage [3] des Werkzeugs genauer zu studieren. (csi/jlu)

Infos

  1. Netcat und Co.: Falko Benthin, “Netzwerker”, LU 01/2023, S. 31, https://www.linux-community.de/48533
  2. Socat: http://www.dest-unreach.org/socat/
  3. Manpage zu Socat: https://linux.die.net/man/1/socat
DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 4 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Nach oben