Après un piratage, mon serveur Hetzner s’est mis à miner du Monero
(blog.jakesaunders.dev)- Une utilisation anormale du CPU a été détectée sur un serveur Hetzner personnel ; l’enquête a révélé qu’un programme de minage de cryptomonnaie Monero (
xmrig) était en cours d’exécution - La cause était l’attaque d’un conteneur de l’outil d’analyse Umami incluant une vulnérabilité d’exécution de code à distance dans Next.js (CVE-2025-66478)
- Heureusement, comme ce conteneur s’exécutait avec un utilisateur non root et sans montage hôte ni élévation de privilèges, l’intrusion est restée confinée à l’intérieur du conteneur
- L’attaquant a exploité une désérialisation non sécurisée des composants serveur Next.js pour exécuter une charge utile malveillante et installer le mineur
- Ce cas illustre l’importance de la gestion des dépendances et des paramètres de sécurité des conteneurs ; l’auteur a renforcé ses mesures de sécurité en activant le pare-feu, en durcissant SSH et en appliquant des mises à jour régulières
Piratage et réponse initiale
- Réception d’un e-mail d’alerte de Hetzner indiquant que le serveur scannait des réseaux externes
- Le message précisait que le serveur pourrait être bloqué sans intervention dans les 4 heures
- Après connexion en SSH, découverte d’un processus utilisant 819 % du CPU dans
/tmp/.XIN-unix/javae, ainsi que de plusieurs processusxmrig - Il a été confirmé que le minage de cryptomonnaie durait depuis environ 10 jours
Enquête sur le vecteur d’intrusion
- Tous les processus malveillants s’exécutaient avec l’utilisateur UID 1001, ce qui correspondait au conteneur Umami
- Un binaire de mineur a été trouvé dans le répertoire
/app/node_modules/next/dist/server/lib/xmrig-6.24.0/ - La commande d’exécution contenait l’adresse du pool de minage
auto.c3pool.org:443ainsi qu’une clé utilisateur
Vulnérabilité Next.js et méthode d’attaque
- La cause était la vulnérabilité de désérialisation des React Server Components de Next.js (CVE-2025-66478)
- Si un attaquant envoie une requête HTTP manipulée, du code arbitraire peut être exécuté sur le serveur
- Cela permet ensuite d’installer et d’exécuter un mineur de cryptomonnaie
- L’auteur pensait « ne pas utiliser Next.js directement », avant de se rendre compte plus tard que Umami repose sur Next.js
Vérification de l’isolation du conteneur
- Confirmation que
/tmp/.XIN-unix/javaen’existait pas sur le système de fichiers hôte- Il s’agissait simplement du fait que la sortie de
docker psaffiche les processus du conteneur ; l’isolation réelle était bien maintenue
- Il s’agissait simplement du fait que la sortie de
- Résultat de
docker inspect- Utilisateur :
nextjs Privileged: falseMounts: aucun
- Utilisateur :
- Le code malveillant ne pouvait donc pas accéder à l’hôte, enregistrer une tâche cron, créer un service système ou installer un rootkit
Restauration et renforcement de la sécurité
- Après arrêt et suppression du conteneur Umami infecté, l’utilisation du CPU est revenue à la normale
- Activation du pare-feu UFW pour n’autoriser que SSH, HTTP et HTTPS
- Après transmission des résultats de l’enquête à Hetzner, le ticket a été clôturé en moins d’une heure
Leçons et points d’amélioration
- Dire « je n’utilise pas X » n’inclut pas forcément les dépendances
- Il faut vérifier sur quelle stack technologique reposent les outils utilisés
- Preuve de l’efficacité de l’isolation des conteneurs
- Utilisateur non root, mode non privilégié et absence de volumes inutiles ont empêché l’extension des dégâts
- Nécessité d’une défense en profondeur (Defense in Depth)
- Pare-feu, fail2ban, monitoring et mises à jour régulières sont indispensables
- Insistance sur l’importance de rédiger soi-même le Dockerfile et de réduire au minimum les privilèges du conteneur
Mesures prises après l’incident
- Redéploiement d’Umami avec la dernière version et audit de tous les conteneurs tiers
- Vérification de l’utilisateur d’exécution, des montages, du calendrier de mise à jour et de la nécessité de chaque conteneur
- Passage à l’authentification par clé SSH, désactivation de la connexion par mot de passe, configuration de fail2ban
- Renforcement du monitoring avec Grafana et Node Exporter, application immédiate des mises à jour de sécurité
Conclusion
- À cause de la vulnérabilité Next.js d’Umami, le serveur a été exploité pendant 10 jours pour miner du Monero, mais
l’isolation du conteneur et l’exécution en non root ont permis de limiter les dégâts - Cette expérience a fait prendre conscience à l’auteur de l’importance de l’identification des dépendances, de la configuration de sécurité et de la gestion des mises à jour
- L’incident a été résolu en environ 2 heures et reste un cas concret validant l’efficacité réelle de la sécurité des conteneurs
1 commentaires
Réactions sur Hacker News
J’utilisais UFW avant, mais maintenant je recommande firewalld
UFW devient difficile à gérer avec le temps, tandis que firewalld est bien plus stable grâce à sa configuration basée sur XML
La commande
firewall-cmdpermet de configurer SSH, HTTPS, le port 80, etc., et il vaut mieux utiliser le backend nftablesDans le cas de Docker, il arrive souvent que des ports soient ouverts en contournant les règles du pare-feu ; il est donc plus sûr de définir
StrictForwardPorts=yesdans/etc/firewalld/firewalld.conf8080:8080, mais le lier à une IP privée comme192.168.0.1:8080:8080Je fais tourner Docker sur une VM 10.0.10.11, accessible uniquement via WireGuard, avec Caddy en reverse proxy, et c’était pratique
Un malware essaiera de se connecter à un pool de minage externe ou à un serveur C2 ; il faut donc bloquer l’accès réseau des binaires non autorisés
Retirer les droits d’exécution sur
/tmp,/var/tmpet/dev/shmest également utilenftables.confà lui seul reste suffisamment simple et clairiptables est déjà obsolète, donc une couche supplémentaire comme firewalld n’est pas forcément nécessaire
Cela semble être lié à React2Shell CVE-2025-55182
C’est étrange qu’une vulnérabilité active depuis plus d’un an ait reçu si peu d’attention
Si vous avez déployé une web app avec Next.js au cours des 12 derniers mois, il y a de fortes chances qu’elle fasse déjà partie d’un botnet
C’est frustrant de voir le secteur se limiter à des conseils du type « utilisez Docker » ou « activez un pare-feu »
En ce moment, l’écosystème frontend me lasse tellement que j’envisage de réorienter ma carrière vers le C++
Aujourd’hui, la combinaison Next.js, React, Tailwind et Postgres s’est imposée comme un standard depuis cinq ans
Comparé à la prolifération de frameworks de la fin des années 2000 et du début des années 2010, c’est bien plus stable
Si vous n’aimez pas les modes et les changements, le développement IA évolue encore bien plus vite
Côté backend, il suffit de s’appuyer sur une stack technique robuste comme .NET, Java ou Go, puis de choisir librement le frontend
Cela réduit le nombre de CVE et la fatigue technologique
Discussion GitHub associée
Si vous limitez l’usage CPU d’un conteneur Docker avec
--cpus="0.5", un service défaillant ou un mineur n’impactera pas tout le systèmeFaire tourner un serveur sans pare-feu est un choix assez audacieux
En utilisant aussi le pare-feu externe de Hetzner, on ajoute une couche de défense supplémentaire en cas d’erreur
Pour ma part, j’autorise SSH uniquement depuis l’IP de mon domicile, et si j’en ai besoin depuis l’extérieur, je l’ouvre temporairement via le site de Hetzner
Ce qui compte vraiment, c’est de ne pas exécuter de logiciels comportant des vulnérabilités RCE
Si Docker a eu l’air de sauver la situation, c’est surtout parce qu’il y a eu de la chance
On peut plutôt mettre en place un bastion host et contrôler les flux entrants/sortants via un proxy HTTP, mais la configuration est complexe
Utiliser des ports non standard s’est révélé étonnamment efficace
Je ne sais pas à quel point c’est vraiment efficace, mais c’est un peu comme un parapluie psychologique
Je me demandais si faire tourner un conteneur Docker en root permettait aussi d’attaquer l’hôte
Pour exécuter du code non fiable, il faut utiliser des VM (KVM/QEMU) ou des technologies comme gVisor(https://gvisor.dev/) et Firecracker(https://firecracker-microvm.github.io/)
Il faut voir Docker non pas comme un sandbox, mais plutôt comme un environnement d’exécution isolé
La configuration par défaut de Docker ne limite ni la RAM, ni le CPU, ni l’usage disque, ce qui le rend aussi vulnérable aux attaques DoS
En plus, beaucoup de guides recommandent des options dangereuses comme
--privilegedouCAP_SYS_PTRACEOn peut aussi lancer un nouveau conteneur et élever ses privilèges en root
Comme ce n’est toujours pas la valeur par défaut dans Docker, le risque d’évasion reste élevé sans configuration explicite
La plupart des évasions de conteneur observées dans le passé auraient pu être bloquées avec les user namespaces
Si le serveur ne traite pas de données sensibles, nettoyer uniquement le conteneur peut suffire
Pour réduire la surface d’attaque, il faut éviter d’exposer publiquement les services qui n’ont pas besoin de l’être
Par exemple, un outil d’analyse peut être rendu accessible uniquement via WireGuard ou un proxy SOCKS sur SSH
J’ai moi aussi subi une infection par un mineur Monero sur un serveur Hetzner
Heureusement, cela s’est limité à un conteneur LXC sous Incus, et comme sa priorité CPU était basse, je ne m’en suis pas rendu compte immédiatement
Une clé SSH avait été ajoutée au compte root et un agent d’administration à distance avait été installé
J’ai fini par jeter le conteneur, mais j’en ai tiré quelques leçons
Le billet contenait des hallucinations d’IA non relues par un humain
Il affirme à plusieurs reprises qu’il s’agit d’une vulnérabilité liée à Puppeteer, alors que c’est faux
En ce moment, des mineurs Monero exploitant une vulnérabilité React 19 sont installés un peu partout
J’ai rencontré le même problème moi aussi
Il agit un peu comme un bug bounty automatique, en signalant la vulnérabilité
Si la surveillance réseau ou des processus est correctement en place, il est facile à détecter
Cela a au moins été une bonne occasion d’améliorer mon système de sauvegarde
Quand je vois ce genre de cas, je me dis que j’ai bien fait de ne plus gérer de VPS moi-même
J’ai déjà essayé, mais je me considère comme un administrateur ordinaire, et je trouve trop difficile de maintenir un bon niveau de sécurité
Du coup, je préfère maintenant confier cela à des spécialistes et payer pour être beaucoup plus tranquille