Détecter le cryptojacking en conteneur avec Falco et Tetragon
Détection cryptojacking Kubernetes Falco : la règle qui repère un binaire lancé depuis /tmp, les connexions vers un pool de minage, et ce qui reste en HITL.
Un conteneur qui consomme 100 % de CPU en continu n'est pas forcément en train de traiter une charge légitime. C'est souvent le symptôme le plus visible d'un cryptojacking : un mineur de crypto-monnaie installé par un attaquant, tournant discrètement sur une infrastructure qui n'est pas la sienne. Le point d'entrée réel n'est presque jamais une image malveillante publiée sciemment sur un registre public : c'est le plus souvent une image légitime, populaire, compromise via une CVE non corrigée, exploitée depuis l'extérieur, puis utilisée pour déposer et lancer un binaire de minage depuis /tmp. La question que se pose un RSSI face à un pic CPU anormal est simple : un de mes conteneurs mine-t-il de la crypto pour un attaquant, et quelle règle Falco le détecte sans noyer l'équipe sous les faux positifs ?
Le scénario réel : de l'image compromise au mineur
La chaîne suit presque toujours le même schéma. Un service exposé publiquement (une API, une application web, un endpoint mal isolé) tourne dans une image dont une dépendance porte une CVE connue, souvent avec un exploit public. L'attaquant obtient l'exécution de code dans le conteneur, télécharge un binaire de minage (XMRig et ses dérivés reviennent le plus souvent) dans un répertoire inscriptible comme /tmp ou un volume monté, puis le lance. Le binaire se connecte ensuite à un pool de minage externe via le protocole Stratum, et consomme le CPU alloué au conteneur pendant des jours, parfois des semaines, avant d'être repéré sur une facture cloud ou un graphique de supervision.
Trois signaux techniques permettent de couper cette chaîne bien avant la facture : l'exécution depuis un répertoire inhabituel, la connexion réseau vers un pool de minage, et la corrélation entre pic CPU et process enfant inattendu sur un conteneur exposé. Aucun des trois pris isolément ne suffit à conclure sans bruit. Ensemble, ils forment une détection fiable.
Règle Falco : exécution depuis /tmp ou un volume monté
Falco observe les appels système au niveau du noyau et expose l'événement spawned_process à chaque nouveau processus. Le signal le plus direct d'un mineur qui démarre est un exécutable dont le chemin (proc.exepath) se trouve dans /tmp, /var/tmp, ou un volume monté dans le conteneur, ce qui n'est presque jamais un comportement d'application légitime en production :
- rule: Binaire exécuté depuis un répertoire inscriptible du conteneur
desc: >
Détecte l'exécution d'un binaire depuis /tmp, /var/tmp ou un volume
monté à l'intérieur d'un conteneur, signal fréquent d'un dépôt
puis lancement de mineur de crypto-monnaie après compromission.
condition: >
spawned_process
and container.id != host
and (proc.exepath startswith /tmp
or proc.exepath startswith /var/tmp
or fd.name startswith /tmp)
and not proc.name in (allowed_tmp_binaries)
output: >
Exécution suspecte depuis un répertoire temporaire
(container=%container.name image=%container.image.repository
proc=%proc.name exepath=%proc.exepath cmdline=%proc.cmdline)
priority: WARNING
tags: [cryptomining, container, process]Le not proc.name in (allowed_tmp_binaries) n'est pas décoratif : sans cette exclusion, la règle déclenche sur toute image de build qui compile ou extrait des artefacts dans /tmp, ce qui est un comportement parfaitement normal pour des pipelines CI ou des images multi-stage. On y revient dans la section anti-faux positifs.
Détecter la connexion sortante vers un pool de minage
Un mineur qui tourne doit parler à un pool pour soumettre ses résultats de calcul. Le protocole le plus courant est Stratum (ports 3333, 4444, 5555, 7777, 8080 selon les pools, souvent en TCP brut ou en TLS sur des ports non standards). Deux approches se combinent : une règle réseau Falco sur les connexions sortantes, et un enrichissement par un feed IOC de domaines et d'adresses de pools connus.
- rule: Connexion sortante vers un pool de minage connu
desc: >
Détecte une connexion réseau sortante depuis un conteneur vers un
domaine ou une adresse IP associée à un pool de minage connu,
ou vers un port Stratum typique sans contexte applicatif attendu.
condition: >
outbound
and container.id != host
and (fd.sip.name in (known_mining_pool_domains)
or fd.rport in (3333, 4444, 5555, 7777, 8080)
or fd.sip in (mining_pool_ip_ioc_list))
output: >
Connexion sortante vers pool de minage suspecté
(container=%container.name proc=%proc.name
dest=%fd.sip.name:%fd.rport cmdline=%proc.cmdline)
priority: CRITICAL
tags: [cryptomining, network, exfiltration]La liste mining_pool_ip_ioc_list doit venir d'un feed IOC entretenu et daté, pas d'une liste figée copiée une fois puis jamais mise à jour : les pools changent d'infrastructure régulièrement, et une liste statique se périme en quelques mois. C'est un travail de curation continue, pas une règle qu'on écrit puis qu'on oublie.
Corréler pic CPU et process enfant inattendu
Un exec depuis /tmp seul peut être un faux positif d'outillage. Une connexion vers un port 3333 seule peut être un test ou un service legacy mal nommé. Ce qui élève la confiance, c'est la corrélation : un conteneur exposé publiquement (donc avec une surface d'attaque directe) qui, en dehors de toute fenêtre de déploiement, fait apparaître un process enfant qu'aucune image de référence ne prévoit, en même temps qu'un pic de consommation CPU soutenu sur plusieurs minutes.
# Repérage manuel côté orchestrateur : conteneurs exposés
# avec un CPU soutenu au-dessus de 90 % et un process enfant
# non présent dans l'image de base
kubectl top pods --containers --sort-by=cpu \
--field-selector metadata.namespace=production
# Cross-check : le pod a-t-il un service exposé publiquement ?
kubectl get svc -n production -o wide | grep LoadBalancerC'est cette corrélation, exec inattendu + connexion Stratum + pic CPU sur une surface exposée, qui distingue un mineur d'un simple bruit d'exploitation, et qui justifie de traiter l'alerte comme critique plutôt que comme une simple ligne de log.
Anti-faux positifs : ne pas alerter aveuglément sur tout exec en /tmp
C'est le point où la plupart des déploiements Falco produisent trop de bruit et finissent ignorés. Trois exclusions structurent une règle utilisable en production :
- Les images de build légitimes. Les images qui compilent, décompressent des archives ou installent des dépendances au démarrage (init containers, jobs CI) écrivent et exécutent régulièrement depuis
/tmp. Scoper la règle en excluant les labels ou les namespaces dédiés au build (namespace != ci-build,container.image.repository not in (build_images)) évite l'essentiel du bruit. - Le scope par namespace et par label. Une règle qui s'applique uniformément à tout le cluster traite un environnement de dev comme un environnement de production exposé. Restreindre la sévérité ou l'activation par label (
k8s.ns.label.environment == "production") concentre l'attention là où le risque est réel. - L'allowlist de binaires connus. Certains outils d'observabilité ou agents de sécurité légitimes déposent eux-mêmes des binaires temporaires. Une allowlist explicite, courte et documentée, vaut mieux qu'une règle qui ignore tout
/tmppar défaut.
La règle qui alerte sur tout exec dans /tmp sans ces trois filtres n'est pas une détection, c'est un générateur de tickets qu'on finit par désactiver. La preuve de sa qualité se fait sur un corpus bénin représentatif de vos propres images avant mise en production, pas sur l'intuition qu'elle "a l'air correcte".
Falco pour la détection, Tetragon pour l'enforcement
Falco observe et alerte, mais n'agit pas par défaut au niveau noyau. Pour l'enforcement, c'est-à-dire bloquer ou tuer le process au moment de l'exécution, Tetragon (eBPF, projet Cilium) permet d'écrire une politique équivalente mais avec une action de blocage active :
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: block-exec-from-tmp
spec:
kprobes:
- call: "security_bprm_check"
syscall: false
args:
- index: 0
type: "linux_binprm"
selectors:
- matchBinaries:
- operator: "Prefix"
values:
- "/tmp/"
- "/var/tmp/"
matchActions:
- action: SigkillLe passage d'une règle Falco (observation) à une politique Tetragon (blocage kernel automatique) est une décision d'enforcement, pas une simple bascule de configuration. Avant de l'activer en mode kill automatique, il faut avoir fait tourner la règle en mode observation seule pendant une période suffisante sur l'environnement cible, et avoir mesuré son taux de faux positifs sur le trafic réel de vos images de build et de vos jobs légitimes. Une politique Tetragon en Sigkill mal scopée peut interrompre un pipeline CI légitime aussi efficacement qu'un mineur.
Quels signaux justifient un kill automatique, lesquels restent en HITL
Tous les signaux ne méritent pas la même réponse automatisée :
- Kill automatique défendable : connexion confirmée vers un pool de minage identifié par IOC daté, combinée à un exec depuis
/tmpsur un conteneur qui n'a aucune raison fonctionnelle d'y exécuter quoi que ce soit (image de production applicative, pas de build). La combinaison des deux signaux réduit fortement le risque de faux positif. - Reste en supervision humaine (HITL) : un exec depuis
/tmpisolé, sans connexion réseau suspecte associée ; un pic CPU sans process enfant inattendu identifié ; toute alerte sur un namespace de build, de CI ou de développement où l'écriture en/tmpest un comportement normal attendu.
Le kill automatique n'est justifié que lorsque la combinaison de signaux dépasse largement le bruit de fond mesuré sur votre propre corpus bénin. Dans tous les autres cas, l'alerte doit remonter à un opérateur qui valide avant toute action de remédiation, en particulier sur des conteneurs de production dont l'arrêt a un coût métier.
En résumé
Détecter un cryptojacking en conteneur ne repose pas sur une seule règle magique : c'est la combinaison d'un signal d'exécution (/tmp, volume monté), d'un signal réseau (pool de minage via IOC daté) et d'un signal de corrélation (pic CPU sur une surface exposée) qui donne une alerte exploitable sans noyer l'équipe. Falco couvre l'observation, Tetragon permet l'enforcement kernel quand la confiance est prouvée, pas supposée.
C'est exactement cette méthode, règles validées sur moteur réel, anti-faux positifs prouvés sur corpus bénin, priorisation par exposition réelle, que nous appliquons dans le pack cloud native ThreatClaw : les règles de détection cryptojacking arrivent prêtes à l'emploi, testées, sans que vous ayez à refaire ce travail de validation vous-même.
Articles liés
Falco et Tetragon détectent l'agent IA en conteneur qui sort de son enveloppe : appel d'outil anormal, spawn de process, escalade par prompt malveillant.
Google observe des clusters attaqués en 18 minutes et des évasions via pods privilégiés. Voici la détection Falco au runtime et les garde-fous OPA à l'admission.
Le scan d'image ne voit rien de ce qui se passe à l'exécution. Guide sur la sécurité runtime conteneurs eBPF avec Falco et Tetragon : règles, exemples et pièges à éviter.
Nous avons détoné un échantillon Phobos vivant. Voici ce qu'il fait, suppression des clichés instantanés, coupure du pare-feu, et la règle Sigma qui l'attrape, validée sur plusieurs échantillons, zéro faux positif.