Comment trouver et supprimer un crypto-mineur sur votre serveur
Dernière mise à jour:
Un mineur de cryptomonnaie est ce que l'on trouve le plus souvent sur un serveur Linux compromis. Il prend tout le CPU qu'il peut pour miner du Monero ou une autre monnaie au profit de quelqu'un d'autre, et le premier signe est souvent un site lent, un ventilateur à fond, une facture de crédits CPU ou un e-mail d'abus de l'hébergeur.
Le mineur lui-même est la partie facile. Ce qui compte, c'est ce qui l'a laissé entrer et ce qui le fait revenir : une tâche cron, une unité systemd, une clé SSH, une bibliothèque préchargée dans chaque processus. Procédez dans l'ordre ci-dessous : repérer, isoler, supprimer, trouver le point d'entrée, durcir. Les commandes sont pour Debian et Ubuntu et pour la famille RHEL ; PID désigne l'identifiant du processus trouvé à l'étape 1.
Repérer le mineur
Commencez par ce qui consomme le CPU. Un mineur occupe en général un processus à 100 % par cœur, qui tourne depuis des jours.
ps -eo pid,user,%cpu,etime,args --sort=-%cpu | head -n 15- Les noms :
xmriget ses variantes, ou des noms choisis pour paraître inoffensifs :kdevtmpfsi,kinsing,kworkerds, un[kthreadd]écrit à la main, une chaîne aléatoire. - Un thread du noyau s'affiche entre crochets et n'a pas de binaire : un nom entre crochets avec un chemin derrière est un faux.
- L'utilisateur : un mineur qui tourne sous
www-data,apache,nginx,redisoupostgresest entré par ce service.
Pour un PID suspect, regardez son binaire, son répertoire de travail, sa ligne de commande complète et l'unité systemd qui l'a lancé :
sudo ls -l /proc/PID/exe /proc/PID/cwd
sudo tr '\0' ' ' < /proc/PID/cmdline; echo
systemctl status PIDUn binaire marqué (deleted), ou qui tourne depuis /tmp, /var/tmp ou /dev/shm, est un signe fort. Cette commande liste tous ces processus d'un coup :
sudo ls -l /proc/[0-9]*/exe 2>/dev/null | grep -E '\(deleted\)|/tmp/|/var/tmp/|/dev/shm/'Quand top ne montre rien : ld.so.preload
Si la charge est élevée mais qu'aucun processus ne l'explique, le mineur se cache peut-être derrière une bibliothèque chargée dans chaque programme via /etc/ld.so.preload. Ce fichier n'existe normalement pas. S'il existe et cite une bibliothèque que vous ne connaissez pas, ps et top vous mentent.
ls -l /etc/ld.so.preload 2>/dev/null && cat /etc/ld.so.preload
sudo grep -l LD_PRELOAD /proc/[0-9]*/environ 2>/dev/nullConnexions vers un pool de minage
Les mineurs dialoguent avec un pool via le protocole stratum. Les ports 3333, 4444, 5555, 7777 et 14444 sont typiques, mais les pools écoutent aussi sur 443 et 80 : regardez donc aussi les connexions du processus lui-même :
sudo ss -tnp state established '( dport = :3333 or dport = :4444 or dport = :5555 or dport = :7777 or dport = :14444 )'
sudo ss -tnp state established | grep PIDLes fichiers de configuration des mineurs contiennent en général l'URL d'un pool. Cette commande les cherche aux endroits habituels :
sudo grep -rIl -E 'stratum\+(tcp|ssl)://|"pools"|donate-level' /tmp /var/tmp /dev/shm /root /home /var/www /etc 2>/dev/nullCe qui le fait revenir
Cherchez la persistance avant de tuer quoi que ce soit, pour savoir quoi supprimer. D'abord cron : les lignes qui téléchargent avec curl ou wget, décodent du base64 ou exécutent quelque chose depuis /tmp.
sudo cat /etc/crontab
sudo ls -la /etc/cron.d /etc/cron.hourly /etc/cron.daily /var/spool/cron 2>/dev/null
for u in $(cut -d: -f1 /etc/passwd); do sudo crontab -l -u "$u" 2>/dev/null | sed "s/^/$u: /"; done
sudo grep -rE 'curl|wget|base64|/tmp/|/dev/shm' /etc/crontab /etc/cron.* /var/spool/cron 2>/dev/nullEnsuite les timers systemd et les fichiers d'unité modifiés ces 30 derniers jours :
systemctl list-timers --all
sudo sh -c "find /etc/systemd/system /usr/lib/systemd/system /lib/systemd/system /root/.config/systemd /home/*/.config/systemd \
-type f \( -name '*.service' -o -name '*.timer' \) -mtime -30 2>/dev/null"Puis les clés SSH que vous n'avez pas ajoutées, rc.local, les fichiers de démarrage du shell et les comptes que vous n'avez pas créés :
sudo sh -c 'cat /root/.ssh/authorized_keys /home/*/.ssh/authorized_keys 2>/dev/null'
ls -l /etc/rc.local 2>/dev/null
sudo sh -c "grep -lE 'curl|wget|/tmp/|/dev/shm' /etc/profile.d/* /etc/bash.bashrc /etc/bashrc /root/.bashrc /root/.profile /home/*/.bashrc 2>/dev/null"
awk -F: '$3 == 0 || $3 >= 1000 {print $1, $3, $7}' /etc/passwdEnfin, vérifiez que les binaires du système n'ont pas été remplacés. La sortie liste les fichiers des paquets dont le contenu a changé ; les fichiers de configuration sont exclus.
sudo dpkg --verify | grep -v ' c /'sudo rpm -Va 2>/dev/null | grep -E '^..5' | grep -v ' c /'L'isoler
Si votre hébergeur permet de faire un snapshot du disque, faites-le maintenant : vous gardez les preuves et un moyen de revenir en arrière. Coupez ensuite le mineur de son pool. Remplacez 198.51.100.23 par l'adresse du pool trouvée à l'étape 1. Cette table nftables fonctionne sur Debian, Ubuntu et la famille RHEL à côté d'ufw ou de firewalld, et disparaît au redémarrage.
sudo nft add table inet quarantine
sudo nft 'add chain inet quarantine out { type filter hook output priority 0; policy accept; }'
sudo nft add rule inet quarantine out ip daddr 198.51.100.23 dropGardez une copie du binaire et de sa ligne de commande avant qu'il ne soit supprimé. /proc/PID/exe fonctionne même si le fichier a déjà été effacé du disque. Le SHA-256 peut être recherché dans les bases publiques de malwares.
sudo mkdir -p /root/evidence
sudo cp /proc/PID/exe /root/evidence/miner.bin
sudo tr '\0' ' ' < /proc/PID/cmdline | sudo tee /root/evidence/cmdline.txt
sudo sha256sum /root/evidence/miner.binGelez d'abord le processus, pour qu'un watchdog ne le voie pas mourir et ne le relance pas aussitôt, regardez son parent, puis tuez-le. Si le parent est un script ou un second processus de minage, occupez-vous-en aussi.
sudo kill -STOP PID
ps -o pid,ppid,user,args -p PID
sudo kill -9 PIDAttention: Considérez que tous les secrets du serveur sont connus : clés SSH, mots de passe, mots de passe des bases de données et clés d'API dans .env et les fichiers de configuration. Changez-les depuis une machine saine, en commençant par les comptes qui donnent accès à d'autres serveurs.
Le supprimer, avec tout ce qui le fait revenir
Supprimez chaque élément de persistance trouvé à l'étape 1, puis les binaires. Pour une unité systemd (remplacez NAME) :
sudo systemctl disable --now NAME.service
sudo rm /etc/systemd/system/NAME.service
sudo systemctl daemon-reload- Cron : supprimez les lignes avec
sudo crontab -e -u USER, ainsi que les fichiers de/etc/cron.dque vous n'avez pas créés. - SSH : supprimez de chaque
authorized_keysles clés que vous ne reconnaissez pas. - Comptes : verrouillez ou supprimez les utilisateurs que vous n'avez pas créés (
sudo usermod -L NAME), et vérifiez/etc/sudoerset/etc/sudoers.d/. - Les binaires et les fichiers de configuration du mineur, partout où l'étape 1 les a trouvés.
Les mineurs rendent souvent leurs fichiers immuables, si bien que rm échoue avec Operation not permitted, même en root. Vérifiez et retirez d'abord les attributs :
sudo lsattr /path/to/file
sudo chattr -i -a /path/to/file
sudo rm /path/to/fileSi /etc/ld.so.preload cite une bibliothèque que vous ne connaissez pas, déplacez le fichier (il est rare qu'un logiciel légitime s'en serve) et supprimez la bibliothèque qu'il indiquait :
sudo mv /etc/ld.so.preload /root/evidence/ld.so.preload
sudo ldconfigRedémarrez, puis vérifiez à nouveau le CPU au bout d'une heure, et le lendemain : si le mineur revient, c'est qu'un élément de persistance ou le point d'entrée est toujours là.
Attention: Si le mineur tournait en root, si des binaires système ont changé ou si ld.so.preload a été utilisé, vous ne pouvez pas être sûr que le serveur est sain. Reconstruisez-le à partir d'une image neuve et restaurez les données depuis une sauvegarde antérieure à l'infection, après l'avoir vérifiée. Nettoyer sur place n'est raisonnable que si le mineur tournait sous un utilisateur non privilégié et que rien n'a changé en dehors des fichiers de cet utilisateur.
Trouver comment il est entré
Si vous ne fermez pas la porte d'entrée, le mineur revient en quelques jours. L'utilisateur sous lequel il tournait et l'heure de création de ses fichiers vous mettent sur la piste :
ps -o user,pid,lstart,args -p PID
sudo stat /path/to/miner- Il tourne sous l'utilisateur du serveur web : un plugin, un thème ou une application vulnérable, ou un formulaire d'upload. Regardez les logs web autour de l'heure où le fichier est apparu.
- Il tourne sous
redis, ou ses fichiers ont été créés par lui : Redis ouvert sur internet sans mot de passe. - Il a été lancé par un conteneur ou par
dockerd: l'API Docker exposée sur 2375 ou 2376. - Il tourne en root ou sous un utilisateur normal avec une connexion juste avant : un mot de passe faible ou une clé SSH volée.
last -i -n 50
sudo journalctl --since "14 days ago" | grep -E "Accepted (password|publickey)"sudo grep -hE 'wget|curl|base64|%2Fbin%2Fsh|/bin/sh' \
/var/log/nginx/access.log* /var/log/apache2/access.log* /var/log/httpd/access_log* 2>/dev/null | tail -n 50Et les services qui sont des portes d'entrée courantes lorsqu'ils écoutent sur toutes les interfaces : l'API Docker, Redis, les consoles web sur 8080, Elasticsearch, MongoDB, Memcached.
sudo ss -tlnp | grep -E ':(2375|2376|6379|8080|9200|27017|11211)\b'Durcir le serveur ensuite
- Fermez le point d'entrée trouvé : mettez à jour ou retirez l'application, liez Redis et les bases de données à localhost avec un mot de passe, n'exposez jamais l'API Docker.
- SSH par clés uniquement et sans connexion root : voir Comment stopper les attaques par force brute SSH.
- Installez les mises à jour, activez les mises à jour de sécurité automatiques et le pare-feu : voir Sécuriser un nouveau VPS : la checklist.
- Limitez le trafic sortant quand c'est possible : un serveur web a rarement besoin d'ouvrir des connexions vers n'importe quel port.
- Surveillez désormais l'usage du CPU, les connexions sortantes et les modifications de cron, de systemd et des clés SSH, pour que le prochain soit repéré en quelques minutes et non en quelques semaines.
Comment InfraFence détecte un mineur de cryptomonnaie
Plusieurs détecteurs d'InfraFence couvrent les étapes ci-dessus, chacun sous un angle différent :
- Détection des processus : un processus en cours dont le nom ou la ligne de commande correspond à un mineur connu (xmrig, minerd, cpuminer et d'autres), à une URL stratum ou à un pool connu est signalé comme critique, avec son PID et sa ligne de commande. Les reverse shells et les scripts qui tournent depuis
/tmpsont signalés aussi. - Analyse antimalware : des signatures pour les mineurs de cryptomonnaie, les web shells et les backdoors dans vos sites, des règles YARA mises à jour chaque jour, et les binaires système comparés à la base des paquets (
dpkg -V/rpm -Va). - Trafic sortant et DNS : les connexions vers des adresses figurant sur des listes publiques de renseignement sur les menaces, et chaque requête DNS reliée au programme qui l'a faite.
- Intégrité des fichiers :
/etc/ld.so.preload, les crontabs, les unités systemd et chaqueauthorized_keyssont hachés et surveillés, et toute modification déclenche aussitôt une alerte. - Des vérifications de durcissement qui signalent les portes d'entrée habituelles : bases de données ouvertes sur internet, logiciels obsolètes, SSH avec mot de passe.
La vérification des processus se base sur les noms et les lignes de commande : un mineur renommé qui lit son pool dans un fichier de configuration ne correspond pas, et reste l'affaire des autres détecteurs. Le nettoyage décrit dans ce guide reste à votre charge.
Questions
- Est-ce que je peux simplement tuer le processus ?
- Il reviendra. Les mineurs installent une tâche cron, une unité systemd ou une clé SSH pour redémarrer, et la faille par laquelle ils sont entrés est toujours ouverte. Supprimez la persistance et fermez le point d'entrée.
- Dois-je réinstaller le serveur ?
- Si le mineur tournait en root, si des binaires système ont changé ou si
/etc/ld.so.preloada été utilisé, oui : vous ne pouvez pas prouver que le serveur est sain. S'il tournait sous un utilisateur non privilégié et que rien d'autre n'a changé, un nettoyage soigneux peut suffire. - Mon hébergeur dit que le serveur mine, mais je ne vois rien. Pourquoi ?
- Le mineur peut être caché via
/etc/ld.so.preload, tourner dans un conteneur, ou ne démarrer qu'à certaines heures depuis cron. Vérifiez le fichier de preload,docker ps, et les connexions que le serveur ouvre au fil du temps.
Essayez gratuitement sur 1 serveur
Starter est gratuit pour un serveur, avec la protection complète et le blocage automatique. Sans carte bancaire.
Installez l'agent en root, avec votre jeton à la place de <TOKEN> :
curl -fsSL https://github.com/infrafence/infrafence-agent/releases/latest/download/install.sh | sudo bash -s -- --token <TOKEN>Le jeton se crée dans le tableau de bord, dans Serveurs › Ajouter un serveur.
