Netcat – Das Schweizer Taschenmesser der Netzwerk-Administration
Netcat, oder abgekürzt nc, wie auch das Shellkommando heißt, ist ein Netzwerk-Tool mit einer großen Bandbreite an Einsatzmöglichkeiten. Es kann verwendet werden, um Netzwerk-Verbindungen zu monitoren, zu testen oder auch um Daten beliebiger Natur über das Netz zu schicken. Netcat ist praktisch in jeder Distribution vorhanden. Es kommt allerdings je nach Distribution in unterschiedlichen Varianten zum Einsatz, die sich nach Umfang der unterstützenden Features unterscheiden. Beispielsweise wird bei Debian-basierten Distributionen wie Ubuntu oder auch Debian selbst das klassische (originale) netcat bereitgestellt. Bei RedHat-ähnlichen Distributionen wie RedHat, CentOS oder Fedora ist dagegen eine Variante aus dem nmap-Projekt enthalten, die ncat heißt und die aktueller ist und einen breiteren Funktionsumfang aufweist. Debian-Nutzer können sich dieses mehr an Features aber durch ein simples Nachinstallieren des nmap-Paketes verfügbar machen.
Syntax
Netcat wird üblicherweise über eine Konsole wie folgt aufgerufen:
nc [Optionen] [IP-Adresse/Hostname] [Port]
Gängige Optionen sind z. B.
-4/-6 | IP-Protokollversion (IPv4 bzw. IPv6) |
-l | Listen-Modus für eingehende Verbindungen über den angegebenen Port |
-p sport | setzt einen Quell-Port für ausgehende Verbindungen |
-U | verwendet UNIX-domain sockets |
-u | verwendet das UDP Protokoll statt des Default-Protokolls TCP |
-v | erhöht die Debug-Ausgabe |
-w timeout | Timeout bei ausgehenden Verbindungsaufbauten |
-z | in Verbindung mit Port-Checks, ohne dass Daten gesendet werden |
Einsatz-Beispiele
Im Folgenden werden einige Beispiele aufgeführt, die die vielfältigen Einsatzmöglichkeiten demonstrieren sollen.
Einfache Verbindungstests (Port-Checks)
Im einfachsten Fall kann Netcat dazu verwendet werden, die Verfügbarkeit von Ports zu testen. Im Fall von TCP-Verbindungen geschieht dies über folgenden Aufruf:
# nc -v -z Remote-Host Port # nc -v -z 10.3.64.1 53 Connection to 10.3.64.1 53 port [tcp/domain] succeeded!
Im Fall von UDP-Diensten muss folgender Aufruf verwendet werden:
# nc -v -z -u Remote-Host Port # nc -v -z -u 10.3.64.1 53 Connection to 10.3.64.1 53 port [udp/domain] succeeded!
In beiden Fällen signalisiert die Ausgabe (erzwungen durch die Option -v), dass der Verbindungsaufbau erfolgreich war und damit der Port grundsätzlich erreichbar ist. Alternativ kann man aber bei Verwendung dieser Aufrufe in Scripten den Return-Code auswerten (wie allgemein üblich heißt 0 erfolgreich und größer 0 nicht erfolgreich).
Portscanner
Wenn andere Mittel fehlen, kann Netcat recht einfach als Portscanner herhalten. Der Aufruf ist, ähnlich wie bei einfachen Port-Checks, auch hier recht übersichtlich:
# nc -v -n -z -w1 Remote-Host StartPort-EndPort
Beispiel: Bei Server 10.2.64.1 soll nach offenen TCP-Ports im Bereich zwischen Port 25 und 443 (einschließlich) gesucht werden.
# nc -v -n -z -w1 10.2.64.1 25-443 Connection to 10.2.64.1 25 port [tcp/] succeeded! nc: connect to 10.2.64.1 port 26 (tcp) failed: Connection refused nc: connect to 10.2.64.1 port 27 (tcp) failed: Connection refused […] nc: connect to 10.2.64.1 port 52 (tcp) failed: Connection refused Connection to 10.2.64.1 53 port [tcp/] succeeded! nc: connect to 10.2.64.1 port 54 (tcp) failed: Connection refused […] nc: connect to 10.2.64.1 port 79 (tcp) failed: Connection refused Connection to 10.2.64.1 80 port [tcp/] succeeded! nc: connect to 10.2.64.1 port 81 (tcp) failed: Connection refused […] nc: connect to 10.2.64.1 port 442 (tcp) failed: Connection refused Connection to 10.2.64.1 443 port [tcp/] succeeded!
Der Scan zeigt hier, dass neben Port 25 (SMTP) auch die Ports für DNS (53), HTTP (80) und HTTPS (443) verfügbar sind.
Banner Grabbing
Netcat eignet sich weiterhin auch zum sog. Banner Grabbing, d. h. zur näheren Untersuchung von entfernten Diensten. Üblicherweise (zumindest für mich :-) ) wird für eine solche Untersuchung das telnet-Kommando verwendet. Der telnet-Client ist allerdings nicht immer installiert, und es zeigt sich, dass auch Netcat diese Aufgabe durchaus genauso gut erfüllen kann.
Banner Grabbing soll hier am Beispiel des SMTP-Dienstes eines entfernten Servers gezeigt werden:
# nc 10.2.64.1 25 220 mail.example.net ESMTP Postfix (Debian/GNU) ==> ehlo test 250-mail.example.net 250-PIPELINING 250-SIZE 102400000 250-VRFY 250-ETRN 250-STARTTLS 250-ENHANCEDSTATUSCODES 250-8BITMIME 250 DSN
(==> bedeutet hierbei die Eingabe von Befehlen oder Daten)
Hier erfahren wir, dass es sich um ein Postfix-SMTP Server handelt in der Debian-Variante.
Man könnte jetzt u. a. noch prüfen, ob es sich um einen offenenes Relay handelt, indem man noch die folgenden Eingaben tätigt:
==> mail from: user@domains.com 250 2.1.0 Ok ==> rcpt to: name@example.net 250 2.1.5 Ok ==> data 354 End data with. ==> From: user@domains.com ==> To: name@example.net ==> Subject: Testmail ==> ==> Testmail ==> . 250 2.0.0 Ok: queued as A6E02238 ==> quit 221 2.0.0 Bye
Womit der SMTP-Handshake erfolgreich abgeschlossen wurde.
In Verbindung mit Webservern funktioniert dies ähnlich:
# nc -v -n 10.2.64.1 80 Connection to 10.2.64.1 80 port [tcp/*] succeeded! GET HTTP HTTP/1.1 400 Bad Request Server: nginx Date: Sun, 16 Dec 2018 19:42:17 GMT Content-Type: text/html Content-Length: 166 Connection: close
<html>
<head><title>400 Bad Request</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx</center>
</body>
</html>
Hier sehen wir u. a., dass wir einen NGINX-Webserver getestet haben.
Datei-Übertragung
In manchen Fällen mag es erforderlich sein, ein File von einem System zu einem anderen zu transferieren, ohne die Möglichkeit zu haben, geeignete File Transfer Mechanismen wie ftp, scp, sftp o. ä. nutzen zu können. Auch hier kann Netcat ein Weg sein, mit einfachen Mitteln ans Ziel zu gelangen.
Vorgehen: Im ersten Schritt öffnen wir einen Port auf dem Zielsystem. Die Ausgabe leiten wir dabei in ein File um:
# nc -l -p 1234 >/tmp/test.txt
Auf dem Ausgangssystem haben wir die Datei test.txt, die wir auf das Zielsystem transferieren möchten. Der Inhalt der test.txt ist wie folgt:
# cat test.txt Dies ist nur ein Test
Der Transfer kann nun mit dem folgenden Aufruf erfolgen:
# nc Remote-Host 1234 <test.txt
Nach Ausführen des Kommandos auf dem Quell-System sollte sich der Listener-Prozess auf dem Zielsystem beendet haben und die Datei test.txt unter /tmp erzeugt haben. Sicherheitshalber sollte man sich davon überzeugen, dass Größe und Inhalt beider Dateien (Quelle und Ziel) identisch sind.
Remote-Shell (Backdoor-Shell)
Netcat kann ebenfalls verwendet werden, eine Shell auf einem entfernten System bereitzustellen. Im „normalen“ Betrieb kann man auf diesem Wege eine Absicherung einrichten, einen Shell-Zugriff zu erlauben, wenn im Zuge von Wartungsarbeiten die Gefahr besteht, sein Standbein auf diesem System, also z.B seine SSH-Verbindung, zu verlieren. Diese Form der Remote-Shell erfordert die netcat-Option -e, die aber bei der Debian/Ubuntu-Variante in der Regel fehlt.
Auf dem Zielsystem wird Netcat mit den folgenden Optionen ausgeführt:
# nc -l -p LocalPort -e /bin/bash
Beispiel:
# nc -l -p 1234 -e /bin/bash
Damit öffnen wir auf dem Zielsystem den TCP-Port 1234 und führen nach erfolgtem Verbindungsaufbau die Shell /bin/bash aus. Auf dem Client kann nun mit dem Aufruf
# nc Remote-Host Remote-Port
der Verbindungsaufbau gestartet werden:
# nc 10.2.64.1 1234
Mit Shell-befehlen können nun Operationen auf dem Zielsystem ausgeführt werden:
hostname -f remotehost.example.net cd /var ls -l drwxr-xr-x 2 root root 4096 Feb 6 2018 backups drwxr-xr-x 26 root root 4096 Feb 5 2018 cache drwxrwsrwt 2 root whoopsie 4096 Aug 10 07:35 crash drwxr-xr-x 2 root root 4096 Feb 2 2018 games drwxr-xr-x 107 root root 4096 Feb 5 2018 lib drwxrwsr-x 3 root staff 4096 Aug 8 2013 local lrwxrwxrwx 1 root root 9 Jun 21 2013 lock -> /run/lock
Chat
Man kann Netcat auch für die Übermittlung von Textnachrichten einsetzen. Ähnlich wie beim Write-Kommando, mit welchem man Nachrichten an einen anderen Benutzer auf dem selben System schicken kann, kann man mit Netcat Nachrichten an einen Benutzer auf einem anderen System schicken. Dazu muss man sich einerseits auf einen definierten Port einigen, und weiterhin muss dieser Port zwischen den Systemen erreichbar sein.
Auf dem empfangenden System muss man mit den Optionen
# nc -l Port
einen Port öffnen.
Auf dem sendenden System connectiert man diesen Port über den folgenden Aufruf:
# nc Remote-Host Port
Auf dem Sender wird nun eine Eingabe über STDIN beim Empfänger über STDOUT ausgegeben.
Beispiel:
+--------------------------------------------+ | Sender | Empfänger | |==========================|=================| | | # nc -l 1234 | +--------------------------------------------+ | # nc 10.2.64.1 1234 | | +--------------------------------------------+ | → Hallo | | +--------------------------------------------+ | | Hallo → | +--------------------------------------------+ | | → Test | +--------------------------------------------+ | Test → | | +--------------------------------------------+
(→ Text: Eingabe von Text; Text → : Ausgabe von Text) Die Verbindung ist bidirektional.,d. h. die Eingabe auf dem Sender wird auf dem Empfänger ausgegeben und eine Eingabe in derselben Session auf dem Empfänger wird auf dem Sender ebenfalls ausgegeben. Anzumerken sei, dass dies nur eine sehr einfache Art des Nachrichtenaustauschs ist und noch dazu vollkommen unverschlüsselt. Btw. neben TCP als Übertragungsprotokoll kann auch UDP verwendet werden.
ssh-ProxyCommand
Hat man Systeme zu administrieren, die nur über einen oder mehrere Jumphosts erreichbar sind, so kann man entweder den umständlichen Weg nehmen und sich Host für Host anmelden, um schließlich auf das Zielsystem zu gelangen, oder man vereinfacht sich die Arbeit und nutzt das ProxyCommand-Feature von ssh. In Verbindung mit Netcat kann man so eine Möglichkeit schaffen, mittels eines ssh-Kommando-Aufrufs quasi direkt (also über einen Hob) auf das Zielsystem zu gelangen. Dabei hat es den Anschein, als würde man die Kette von Jumphosts zwischen Quelle und Ziel einfach überspringen. An einem einfachen Beispiel will ich darstellen, wie die Konfiguration aussehen kann:
Szenario:
Quelle → Jumphost → Zielsystem
Konfigurationsbeispiel:
# cat /home/user/.ssh/config Host [Zielsystem] ProxyCommand ssh user@[Jumphost] nc -w2 %h 22 User user
Also konkret:
Host 172.16.1.1 ProxyCommand ssh user@10.2.64.1 nc -w2 %h 22 User user
# ssh -F /home/user/.ssh/config 172.16.1.1 user@10.2.64.1's password: user@172.16.1.1's password: user@172.16.1.1:~$
Die Authentifizierungsschritte auf Jumphost und Zielsystem müssen natürlich durchgeführt werden, können aber u. U. durch eine geeignete Verwendung von ssh-Keys vereinfacht werden. Netcat dient hier als Mittler, der einen entsprechenden Socket für die Verbindung zum nächsten Host ermöglicht und durchreicht.
Soweit eine Übersicht über Netcat, welches nicht umsonst das Schweizer Taschenmesser der Netzwerk-Administration bezeichnet wird. Es gibt noch eine ganze Reihe weiterer Einsatzmöglichkeiten, und durch die Universalität dieses Tools kann man mit ein wenig Fantasie noch weitere Möglichkeiten finden. Es sei aber noch darauf hingewiesen, dass so gut dieses Tool einen Administrator bei seiner Arbeit unterstützen kann, so gut kann es auch unliebsame Besucher/Eindringlinge unterstützen. Hinsichtlich der Absicherung von Systemen sollte daher durchaus abgewägt werden, inwieweit Tools wie Netcat oder ähnliche in den Installationsumfang von Systemen insb. Frontendsystemen gehört.
Frank Möller
Senior Technical Consultant
Quellen:
Offizielle Seite: GNU netcat
Erweiterte Variante: nmap Variante