InfraFenceInfraFence

Live Security Operations

Commencer

Comment détecter et supprimer un rootkit /etc/ld.so.preload

Dernière mise à jour:

/etc/ld.so.preload liste des bibliothèques que l'éditeur de liens dynamique charge dans chaque programme avant tout le reste. Sur un serveur normal, ce fichier n'existe pas. Les attaquants qui obtiennent root y inscrivent une bibliothèque qui remplace des fonctions de la bibliothèque C, comme celles qui listent les répertoires ou ouvrent les fichiers, pour que ps, top, ls, netstat et ss ne montrent plus leurs processus, fichiers et connexions. Des kits open source comme libprocesshider, Azazel et Jynx fonctionnent ainsi, tout comme plusieurs familles de crypto-mineurs et de portes dérobées.

Le point faible de la technique : elle ne fonctionne que sur les programmes qui chargent la bibliothèque C. Les outils liés statiquement, la lecture directe de /proc et un examen depuis l'extérieur du système en marche la contournent. Ci-dessous : comment vérifier, comment nettoyer, et quand reconstruire plutôt. Les commandes sont pour Debian et Ubuntu et pour la famille RHEL ; /usr/lib/libhide.so désigne la bibliothèque que vous trouvez.

Comprendre comment se cache un rootkit par préchargement

  • Les processus : ps et top lisent le répertoire /proc ; un readdir() détourné saute les identifiants de processus de l'attaquant.
  • Les fichiers : le même détournement cache des fichiers par leur nom, souvent /etc/ld.so.preload lui-même et la bibliothèque : ls et cat disent alors qu'ils n'existent pas.
  • Les connexions : netstat et ss perdent les lignes des sockets de l'attaquant.
  • Tout le reste fonctionne normalement, et c'est le but : le serveur paraît sain à tous les outils auxquels vous feriez habituellement confiance.

Ce à quoi il ne peut pas échapper : les programmes qui n'utilisent pas la bibliothèque C du système (des binaires liés statiquement comme busybox-static), le noyau, et un système démarré depuis un autre support. Un rootkit chargé comme module du noyau est un autre cas, plus difficile : il se cache de /proc lui-même, et les vérifications ci-dessous peuvent le manquer.

Vérifier avec des outils que le rootkit ne peut pas tromper

Obtenir un busybox lié statiquement

busybox-static est un seul binaire qui contient ls, cat, grep, sh et d'autres, lié sans la bibliothèque C : une bibliothèque préchargée ne s'y charge jamais. ldd doit répondre not a dynamic executable.

Debian / Ubuntu
sudo apt install busybox-static
ldd /bin/busybox

La famille RHEL n'a pas de busybox statique dans ses dépôts de base. Copiez-en un depuis une machine Debian ou Ubuntu saine (après y avoir installé busybox-static), et appelez-le /root/busybox au lieu de busybox dans les commandes ci-dessous :

Sur votre machine saine
scp /bin/busybox root@SERVER_IP:/root/busybox
ssh root@SERVER_IP 'chmod 700 /root/busybox && ldd /root/busybox'

Remarque: Installer un paquet sur un serveur compromis passe par son propre gestionnaire de paquets, lié dynamiquement. Une copie depuis une machine saine est l'option la plus fiable, quelle que soit la distribution.

Lire le fichier directement

Comparez ce que voit busybox avec ce que voient les outils du système. Si busybox montre le fichier alors que ls et cat habituels disent qu'il n'existe pas, un rootkit est actif en ce moment même.

Toutes distributions
sudo busybox ls -la /etc/ld.so.preload
sudo busybox cat /etc/ld.so.preload
ls -la /etc/ld.so.preload
cat /etc/ld.so.preload

Pour chaque bibliothèque citée dans le fichier, vérifiez si un paquet la possède. De rares usages légitimes existent, comme l'enregistreur de commandes Snoopy et certains agents de supervision, et ils viennent d'un paquet que vous avez installé :

Debian / Ubuntu
dpkg -S /usr/lib/libhide.so
RHEL, Rocky Linux, AlmaLinux, Oracle Linux, Fedora
rpm -qf /usr/lib/libhide.so

Une bibliothèque qu'aucun paquet ne possède est suspecte. Notez sa taille et son empreinte, regardez les noms qu'elle contient (fonctions détournées comme readdir, le mot /proc), et voyez quels processus l'ont chargée :

Toutes distributions
sudo busybox ls -la /usr/lib/libhide.so
sudo busybox sha256sum /usr/lib/libhide.so
sudo busybox strings /usr/lib/libhide.so | busybox grep -iE 'readdir|/proc|preload|hide' | busybox head
Toutes distributions
sudo busybox sh -c "busybox grep -l '/usr/lib/libhide.so' /proc/[0-9]*/maps"

Comparer /proc et ps

busybox lit /proc sans le détournement ; ps le subit. Chaque identifiant de processus que busybox trouve et que ps ne trouve pas est caché, et la ligne affiche son binaire. Des processus terminés pendant la boucle peuvent apparaître une fois : lancez-la deux fois, et regardez les identifiants présents les deux fois.

Toutes distributions
sudo busybox sh -c 'for d in /proc/[0-9]*; do p=${d#/proc/}; /bin/ps -p "$p" > /dev/null 2>&1 || echo "$p $(busybox readlink "$d/exe")"; done'

Même chose pour les connexions réseau : le netstat de busybox lit /proc/net directement. Une connexion présente dans la première liste et absente de la seconde est cachée.

Toutes distributions
sudo busybox netstat -tan
sudo ss -tanp

LD_PRELOAD dans les environnements et les services

La même technique fonctionne processus par processus, via la variable LD_PRELOAD dans un fichier d'unité, un profil de shell ou /etc/environment. Cherchez-la dans les processus en cours et dans les fichiers habituels :

Toutes distributions
sudo busybox sh -c "busybox grep -l LD_PRELOAD /proc/[0-9]*/environ"
sudo busybox grep -rs LD_PRELOAD /etc/environment /etc/profile /etc/profile.d /etc/bash.bashrc /etc/bashrc \
  /etc/systemd /lib/systemd/system /usr/lib/systemd/system /root/.bashrc /root/.profile

Binaires système modifiés

Certains kits remplacent aussi ps, ls ou sshd. La base de données des paquets liste les fichiers empaquetés dont le contenu a changé (fichiers de configuration exclus) :

Debian / Ubuntu
sudo dpkg --verify | grep -v ' c /'
RHEL, Rocky Linux, AlmaLinux, Oracle Linux, Fedora
sudo rpm -Va 2>/dev/null | grep -E '^..5' | grep -v ' c /'

La méthode sûre : depuis un système de secours

dpkg et rpm sont eux aussi liés dynamiquement. Pour un résultat fiable, démarrez le système de secours de l'hébergeur, montez le disque du serveur et lisez le fichier là, où rien du serveur ne tourne. Trouvez d'abord la partition racine avec lsblk : /dev/sda1 n'est qu'un exemple.

Système de secours
lsblk -f
mount /dev/sda1 /mnt
ls -la /mnt/etc/ld.so.preload && cat /mnt/etc/ld.so.preload

Supprimer le rootkit par préchargement

Si l'hébergeur peut faire un snapshot du disque, faites-le d'abord. Gardez ensuite une copie du fichier et de la bibliothèque comme preuves :

Toutes distributions
sudo busybox mkdir -p /root/evidence
sudo busybox cp -a /etc/ld.so.preload /usr/lib/libhide.so /root/evidence/
sudo busybox sha256sum /root/evidence/*

Les rootkits rendent souvent leurs fichiers immuables, si bien que même root obtient Operation not permitted. Le busybox-static de Debian n'a pas de chattr ; les lsattr et chattr du système fonctionnent ici, car les kits par préchargement cachent les fichiers par leur nom et ne touchent généralement pas aux attributs :

Toutes distributions
sudo lsattr /etc/ld.so.preload /usr/lib/libhide.so
sudo chattr -i -a /etc/ld.so.preload /usr/lib/libhide.so

Supprimez le fichier de préchargement avec busybox. À partir du prochain programme lancé, plus rien n'est préchargé, et le ls habituel confirme que le fichier a disparu :

Toutes distributions
sudo busybox rm /etc/ld.so.preload
ls -la /etc/ld.so.preload

Les processus déjà en cours ont toujours la bibliothèque chargée, mais les nouveaux ps et ss que vous lancez ne l'ont plus : ce qui était caché devient visible. Cherchez-le, et gelez ce qui n'a rien à faire là avant de le tuer :

Toutes distributions
ps -ef --forest | less
sudo ss -tanp
sudo kill -STOP PID

Supprimez ce qui le fait revenir : tâches cron, unités systemd, clés SSH et comptes, comme dans Comment trouver et supprimer un crypto-mineur sur votre serveur, qui passe chaque emplacement en revue. Supprimez ensuite la bibliothèque et redémarrez, pour qu'aucun processus en cours ne la garde :

Toutes distributions
sudo busybox rm /usr/lib/libhide.so
sudo ldconfig
sudo reboot

Attention: 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 les fichiers de configuration. L'attaquant avait root. Changez-les depuis une machine saine.

Décider quand reconstruire le serveur

Écrire /etc/ld.so.preload demande root. Une fois qu'un attaquant a eu root, le nettoyage retire ce que vous avez trouvé, pas forcément tout ce qui était là. Reconstruisez depuis une image neuve si l'un de ces points est vrai :

  • Des binaires système ont changé (la vérification des paquets ci-dessus).
  • Le noyau est marqué « tainted » par un module inconnu, ou lsmod liste un module que vous ne savez pas expliquer.
  • Vous n'avez pas trouvé par où l'attaquant est entré.
  • Le serveur contient des données clients, des données de paiement ou des identifiants vers d'autres systèmes.
Toutes distributions
cat /proc/sys/kernel/tainted
lsmod | sort | head -50
sudo dmesg | grep -iE 'taint|module verification|unsigned'

0 dans tainted correspond à un noyau sain ; les autres valeurs ont des causes, comme des pilotes propriétaires : vérifiez-les avant de conclure. Pour reconstruire : créez un nouveau serveur depuis l'image de l'hébergeur, mettez-le à jour, restaurez les données (pas les programmes ni une configuration que vous ne pouvez pas vérifier) depuis une sauvegarde antérieure à l'infection, changez tous les secrets, puis basculez le trafic. La checklist du nouveau VPS couvre la première heure.

Comment InfraFence détecte les rootkits ld.so.preload

L'agent InfraFence est un programme lié statiquement : il ne charge pas la bibliothèque C du système, donc une bibliothèque préchargée ne s'exécute pas en lui et ne peut pas cacher de fichiers ni de processus à ce que l'agent lit lui-même.

  • Intégrité des fichiers : /etc/ld.so.preload fait partie des fichiers surveillés, avec une empreinte SHA-256 comparée toutes les 30 minutes. Une modification est signalée comme événement critique integrity_change avec l'ancienne et la nouvelle empreinte. Voir Intégrité des fichiers et persistance.
  • Analyse de malwares, intégrité du système : un /etc/ld.so.preload contenant des entrées est un résultat critique qui affiche son contenu ; les processus présents dans /proc mais absents de ps sont signalés comme cachés ; les exécutables dans /tmp et /dev/shm et les binaires système modifiés depuis l'installation de leur paquet (dpkg -V, rpm -Va) sont signalés aussi. Voir Malware.
  • La même surveillance couvre la persistance qui l'accompagne d'habitude : crontabs, unités systemd, authorized_keys et sudoers.

Limites : les empreintes sont prises au démarrage de l'agent, donc la surveillance d'intégrité signale les modifications d'un fichier qui existait alors ; un /etc/ld.so.preload qui apparaît plus tard, sur un serveur qui n'en avait pas, est trouvé par l'analyse de malwares. Les analyses tournent selon le calendrier que vous fixez (les analyses automatiques sont désactivées par défaut) ou quand vous cliquez sur **Analyser maintenant**. Un rootkit chargé comme module du noyau peut aussi se cacher de /proc, et InfraFence n'a pas de détection dédiée pour ce cas. InfraFence ne supprime jamais /etc/ld.so.preload ni la bibliothèque : le nettoyage et la décision de reconstruire restent à votre charge.

Questions

/etc/ld.so.preload est-il toujours malveillant ?
Non, mais il est rare. Un serveur normal n'en a pas. Quelques outils légitimes l'utilisent, comme l'enregistreur de commandes Snoopy, et ils viennent d'un paquet que vous avez installé : dpkg -S ou rpm -qf sur la bibliothèque vous le dira.
Supprimer le fichier suffit-il ?
Cela arrête la dissimulation pour chaque nouveau programme, c'est pourquoi c'est la première étape. Cela ne retire pas ce que l'attaquant a fait avec root : persistance, autres portes dérobées, secrets volés. C'est à cela que servent le reste du nettoyage, ou une reconstruction.
rkhunter et chkrootkit le trouvent-ils ?
Ils cherchent les bibliothèques préchargées et les kits connus, et valent la peine d'être lancés. Ce sont des scripts qui appellent les outils du système : sur un système infecté, on peut leur montrer la même vue tronquée. Lancez-les depuis un système de secours pour un résultat fiable.

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.