1 points par GN⁺ 2025-12-19 | 1 commentaires | Partager sur WhatsApp
  • 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 processus xmrig
  • 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:443 ainsi 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/javae n’existait pas sur le système de fichiers hôte
    • Il s’agissait simplement du fait que la sortie de docker ps affiche les processus du conteneur ; l’isolation réelle était bien maintenue
  • Résultat de docker inspect
    • Utilisateur : nextjs
    • Privileged : false
    • Mounts : aucun
  • 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

 
GN⁺ 2025-12-19
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-cmd permet de configurer SSH, HTTPS, le port 80, etc., et il vaut mieux utiliser le backend nftables
    Dans 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=yes dans /etc/firewalld/firewalld.conf

    • Il vaut mieux ne pas ouvrir un port comme 8080:8080, mais le lier à une IP privée comme 192.168.0.1:8080:8080
      Je fais tourner Docker sur une VM 10.0.10.11, accessible uniquement via WireGuard, avec Caddy en reverse proxy, et c’était pratique
    • Il est recommandé d’installer Podman à la place de Docker. Les problèmes de contournement du pare-feu sont fréquents avec Docker
    • Quel que soit le frontend netfilter utilisé, c’est inutile sans restriction des connexions sortantes
      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/tmp et /dev/shm est également utile
    • Hetzner fournit un service de pare-feu externe gratuit, qui peut servir de première ligne de défense
    • Personnellement, je trouve que nftables.conf à lui seul reste suffisamment simple et clair
      iptables 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++

    • Le rythme de renouvellement technologique du frontend s’est beaucoup calmé par rapport à avant
      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
    • On peut très bien créer une web app sans utiliser les derniers frameworks JS
      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
    • Mon instance Pangolin a également été compromise par cette vulnérabilité
      Discussion GitHub associée
    • J’ai moi aussi déployé une centaine de frontends Next.js, mais heureusement ils n’utilisaient pas les Server Components, donc ils n’ont pas été affectés
  • 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ème

    • Faire tourner les conteneurs en mode read-only peut aussi réduire davantage la surface d’attaque
    • En revanche, si la limite CPU est trop basse, l’intrusion peut passer inaperçue plus longtemps et retarder la détection
    • Il faut bien connaître le profil de performance de l’application. En cas de pic de trafic plus tard, elle pourrait être bridée de manière involontaire
    • Il est aussi conseillé de configurer des limites mémoire soft/hard
  • Faire 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

    • Dans la plupart des cas, un pare-feu n’a pas un grand effet
      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
    • Pour un service web public, un pare-feu n’aide pas beaucoup
      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
    • En 30 ans d’administration Linux, les seules fois où je me suis fait pirater, c’était en laissant ouverts des ports bien connus
      Utiliser des ports non standard s’est révélé étonnamment efficace
    • Laisser l’authentification par mot de passe activée est risqué. Personnellement, je ne pense pas que fail2ban soit indispensable
    • Je change le port SSH de manière aléatoire pour éviter les scanners de ports
      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

    • Docker n’est pas une frontière de sécurité. Il fournit seulement une isolation au niveau des processus
      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é
    • Un attaquant peut aussi utiliser le CPU depuis l’intérieur du conteneur pour faire du minage de Monero
      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 --privileged ou CAP_SYS_PTRACE
    • En mode privileged, il est possible d’accéder au système de fichiers root de l’hôte via le socket Docker
      On peut aussi lancer un nouveau conteneur et élever ses privilèges en root
    • Il faut activer les user namespaces pour disposer d’une vraie frontière de sécurité
      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
    • Des évasions de conteneur existent, mais dans la plupart des cas il s’agit simplement d’attaques de minage automatisées
      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

    • Il faut partir du principe qu’un système sera un jour compromis et configurer l’isolation et les limites de ressources en conséquence
    • Maintenir régulièrement des snapshots ZFS et des sauvegardes facilite la restauration
    • Idéalement, un système compromis doit être jeté, mais selon le contexte, un rollback puis un durcissement peuvent aussi convenir
    • Le mineur s’est fait remarquer parce qu’il était mal configuré, mais s’il s’était introduit discrètement, je ne l’aurais peut-être jamais su
    • Cela s’est produit dans un conteneur où Umami était installé
  • 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

    • Le premier paragraphe du texte original indiquait explicitement qu’il s’agissait d’une transcription d’une session Claude
  • 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

    • Ce type de malware de minage est finalement plutôt utile, car il est visible et cause peu de dégâts
      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
    • Sur Oracle Cloud, un serveur Umami a été infecté, et j’ai dû réinitialiser le serveur
      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