Détecter les reverse shells sans croire qu'une règle Sigma suffit
La détection des reverse shells demande du contexte processus, réseau et workload. Les signatures seules ratent trop de cas réels.
Détecter un reverse shell est pénible parce que la primitive est simple. Un processus ouvre une connexion sortante et raccorde entrée, sortie et erreur vers un shell ou un interpréteur. Vu de loin, cela ressemble parfois à une attaque. Vu de près, cela ressemble parfois à un script d'administration mal fichu.
La détection faible dit : alerte quand bash parle à Internet. Elle attrapera quelques tests. Elle ratera aussi les callbacks en Python, les wrappers légitimes détournés, les conteneurs, les shells via outils d'administration, et tout ce qui passe par un chemin déjà bruyant dans votre environnement.
Le processus donne l'intention
Les logs réseau indiquent qu'une connexion existe. La télémétrie processus explique pourquoi elle est suspecte.
Les signaux utiles : shell enfant d'un serveur web, interpréteur lancé par php-fpm, processus système qui ouvre une connexion sortante inhabituelle, cmd.exe ou PowerShell créé par un service exposé, processus très court qui établit une session réseau juste après une entrée utilisateur étrange. Sur Linux, auditd, eBPF ou un EDR correct peuvent aider si argv, parent PID et utilisateur sont conservés. Sur Windows, Sysmon Event ID 1 combiné aux événements réseau donne déjà une base exploitable.
Une hypothèse de requête ressemble à ceci :
process.name in ("sh", "bash", "dash", "zsh", "cmd.exe", "powershell.exe", "python", "perl", "php", "ruby")
AND network.direction = "outbound"
AND destination.ip NOT IN approved_admin_ranges
Ce n'est pas une règle prête pour la production. C'est un point de départ. Les exclusions et le contexte font la différence.
Le parent process raconte souvent l'histoire
bash lancé depuis une session SSH interactive peut être normal. bash lancé par nginx, apache2, php-fpm, postgres, jenkins ou un convertisseur de documents mérite une alerte beaucoup plus sérieuse.
Les attaquants le savent. Ils se cachent derrière des interpréteurs, des jobs planifiés et des outils présents sur la machine, parce que beaucoup de détections regardent le nom de l'outil au lieu du comportement. Un reverse shell en Python peut ne contenir aucune chaîne facilement détectable. Juste un socket, un sous-processus et du plumbing de descripteurs de fichiers.
Le matching de chaînes ne suffit pas.
Le réseau reste indispensable
Les connexions sortantes vers des ports hauts sur des ASN résidentiels sont rarement anodines depuis un serveur. Les sessions longues depuis des workloads qui ne parlent normalement qu'à une base de données, une file de messages ou une API interne sont intéressantes aussi. DNS aide quand la destination est un domaine jetable, mais les callbacks directs vers une IP restent courants dans les labs et les attaques opportunistes.
En conteneur, enrichissez l'alerte avec le pod, le namespace, l'image et le service account. Sans ça, l'analyste reçoit une IP de noeud et un nom de processus. C'est maigre.
Le coût des faux positifs
Les règles reverse shell bruyantes finissent muettes. Les scripts de backup lancent des shells. Les runners CI exécutent des interpréteurs. Les SRE lancent des diagnostics pendant les incidents. Si la détection traite toute connexion sortante d'un shell comme critique, l'équipe la désactivera.
Il faut des niveaux. Critique pour un shell enfant d'un service exposé. Moyen pour un shell réseau inhabituel sur serveur. Faible sur poste développeur sauf destination, parent process ou ligne de commande franchement suspecte.
La bonne détection n'est pas une règle unique. C'est un graphe court : parent, ligne de commande, utilisateur, destination, rôle du workload, heure, historique de la machine.