InfraFenceInfraFence

Live Security Operations

Inizia

Come trovare e rimuovere un rootkit in /etc/ld.so.preload

Ultimo aggiornamento:

/etc/ld.so.preload elenca librerie che il linker dinamico carica in ogni programma prima di qualunque altra cosa. Su un server normale il file non esiste. Gli attaccanti che ottengono root ci scrivono una libreria che sostituisce funzioni della libreria C, come quelle che elencano le directory o aprono i file, così ps, top, ls, netstat e ss non mostrano più i processi, i file e le connessioni dell'attaccante. Kit open source come libprocesshider, Azazel e Jynx funzionano così, e così diverse famiglie di crypto miner e backdoor.

Il punto debole del trucco è che funziona solo sui programmi che caricano la libreria C. Gli strumenti linkati staticamente, la lettura diretta di /proc e uno sguardo da fuori del sistema in esecuzione lo aggirano. Qui sotto: come controllare, come pulire e quando invece reinstallare. I comandi sono per Debian e Ubuntu e per la famiglia RHEL; /usr/lib/libhide.so sta per la libreria che trovi.

Capire come si nasconde un rootkit di preload

  • Processi: ps e top leggono la directory /proc; una readdir() intercettata salta gli ID dei processi dell'attaccante.
  • File: lo stesso aggancio nasconde i file per nome, spesso compresi /etc/ld.so.preload stesso e la libreria, così ls e cat dicono che non esistono.
  • Connessioni: netstat e ss perdono le righe dei socket dell'attaccante.
  • Tutto il resto funziona normalmente, ed è proprio questo lo scopo: il server sembra pulito a ogni strumento di cui di solito ti fideresti.

Ciò a cui non può nascondersi: i programmi che non usano la libreria C del sistema (binari linkati staticamente come busybox-static), il kernel, e un sistema avviato da un altro supporto. Un rootkit caricato come modulo del kernel è un altro caso, più difficile: si nasconde anche a /proc, e i controlli qui sotto possono non vederlo.

Controllare con strumenti che il rootkit non può ingannare

Procurarsi un busybox linkato staticamente

busybox-static è un unico binario con ls, cat, grep, sh e altro, linkato senza la libreria C, quindi una libreria precaricata non si carica mai al suo interno. ldd deve rispondere not a dynamic executable.

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

La famiglia RHEL non ha un busybox statico nei repository di base. Copialo da una macchina Debian o Ubuntu pulita (dopo averci installato busybox-static), e richiamalo come /root/busybox invece di busybox nei comandi qui sotto:

Sulla tua macchina pulita
scp /bin/busybox root@SERVER_IP:/root/busybox
ssh root@SERVER_IP 'chmod 700 /root/busybox && ldd /root/busybox'

Nota: Installare un pacchetto su un server compromesso passa dal suo gestore di pacchetti, linkato dinamicamente. Una copia da una macchina pulita è l'opzione più affidabile su qualsiasi distribuzione.

Leggere il file direttamente

Confronta quello che vede busybox con quello che vedono gli strumenti del sistema. Se busybox mostra il file e i normali ls e cat dicono che non esiste, un rootkit è attivo in questo momento.

Qualsiasi distribuzione
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

Per ogni libreria nominata nel file, verifica se appartiene a un pacchetto. Esistono rari usi legittimi, come il logger di comandi Snoopy e alcuni agent di monitoraggio, e arrivano da un pacchetto che hai installato tu:

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

Una libreria che non appartiene a nessun pacchetto è sospetta. Annota dimensione e hash, guarda i nomi che contiene (funzioni intercettate come readdir, la parola /proc) e quali processi l'hanno caricata:

Qualsiasi distribuzione
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
Qualsiasi distribuzione
sudo busybox sh -c "busybox grep -l '/usr/lib/libhide.so' /proc/[0-9]*/maps"

Confrontare /proc con ps

busybox legge /proc senza l'aggancio; ps lo usa. Ogni ID di processo che busybox trova e ps no è nascosto, e la riga ne mostra il binario. I processi terminati durante il ciclo possono comparire una volta: eseguilo due volte e guarda gli ID che compaiono entrambe le volte.

Qualsiasi distribuzione
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'

Lo stesso per le connessioni di rete: il netstat di busybox legge /proc/net direttamente. Una connessione presente nel primo elenco e assente nel secondo è nascosta.

Qualsiasi distribuzione
sudo busybox netstat -tan
sudo ss -tanp

LD_PRELOAD negli ambienti e nei servizi

Lo stesso trucco funziona per singolo processo, con la variabile LD_PRELOAD in un file di unità, un profilo della shell o /etc/environment. Cercala nei processi in esecuzione e nei file abituali:

Qualsiasi distribuzione
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

Binari di sistema modificati

Alcuni kit sostituiscono anche ps, ls o sshd. Il database dei pacchetti elenca i file pacchettizzati il cui contenuto è cambiato (file di configurazione esclusi):

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 /'

Il modo sicuro: da un sistema di rescue

Anche dpkg e rpm sono linkati dinamicamente. Per un risultato su cui contare, avvia il sistema di rescue del provider, monta il disco del server e leggi lì il file, dove non gira niente del server. Trova prima la partizione root con lsblk: /dev/sda1 è un esempio.

Sistema di rescue
lsblk -f
mount /dev/sda1 /mnt
ls -la /mnt/etc/ld.so.preload && cat /mnt/etc/ld.so.preload

Rimuovere il rootkit di preload

Se il provider può fare uno snapshot del disco, fallo prima. Poi tieni una copia del file e della libreria come prova:

Qualsiasi distribuzione
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/*

I rootkit rendono spesso immutabili i loro file, così anche root riceve Operation not permitted. Il busybox-static di Debian non ha chattr; qui funzionano lsattr e chattr del sistema, perché i kit di preload nascondono i file per nome e di solito non toccano gli attributi:

Qualsiasi distribuzione
sudo lsattr /etc/ld.so.preload /usr/lib/libhide.so
sudo chattr -i -a /etc/ld.so.preload /usr/lib/libhide.so

Rimuovi il file di preload con busybox. Dal prossimo programma avviato in poi non viene più precaricato niente, e il normale ls conferma che il file non c'è più:

Qualsiasi distribuzione
sudo busybox rm /etc/ld.so.preload
ls -la /etc/ld.so.preload

I processi già in esecuzione hanno ancora la libreria caricata, ma i nuovi ps e ss che avvii no, quindi ciò che era nascosto adesso si vede. Cercalo, e congela ciò che non c'entra prima di ucciderlo:

Qualsiasi distribuzione
ps -ef --forest | less
sudo ss -tanp
sudo kill -STOP PID

Rimuovi ciò che lo riporta: cron, unità systemd, chiavi SSH e account, come in Come trovare e rimuovere un crypto miner dal server, che passa in rassegna ogni posto. Poi cancella la libreria e riavvia, così nessun processo in esecuzione la tiene:

Qualsiasi distribuzione
sudo busybox rm /usr/lib/libhide.so
sudo ldconfig
sudo reboot

Attenzione: Considera noto ogni segreto sul server: chiavi SSH, password, password dei database e chiavi API nei file di configurazione. L'attaccante aveva root. Cambiali da una macchina pulita.

Decidere quando reinstallare il server

Scrivere /etc/ld.so.preload richiede root. Quando un attaccante ha avuto root, la pulizia rimuove ciò che hai trovato, non per forza tutto ciò che c'era. Reinstalla da un'immagine pulita quando vale una di queste condizioni:

  • Sono cambiati dei binari di sistema (il controllo dei pacchetti qui sopra).
  • Il kernel è marcato tainted da un modulo sconosciuto, o lsmod elenca un modulo che non sai spiegare.
  • Non hai trovato come è entrato l'attaccante.
  • Il server contiene dati dei clienti, dati di pagamento o credenziali per altri sistemi.
Qualsiasi distribuzione
cat /proc/sys/kernel/tainted
lsmod | sort | head -50
sudo dmesg | grep -iE 'taint|module verification|unsigned'

0 in tainted è un kernel pulito; altri valori hanno le loro ragioni, come i driver proprietari, quindi verificale prima di trarre conclusioni. Per reinstallare: prepara un nuovo server dall'immagine del provider, aggiornalo, ripristina i dati (non programmi o configurazioni che non puoi verificare) da un backup fatto prima dell'infezione, cambia ogni segreto, poi sposta il traffico. La checklist per un nuovo VPS copre la prima ora.

Come InfraFence rileva i rootkit di ld.so.preload

L'agent di InfraFence è un programma linkato staticamente: non carica la libreria C del sistema, quindi una libreria precaricata non gira al suo interno e non può nascondere file o processi a ciò che l'agent legge da sé.

  • Integrità dei file: /etc/ld.so.preload è tra i file sorvegliati, con un'impronta SHA-256 confrontata ogni 30 minuti. Una sua modifica viene segnalata come evento critico integrity_change con il vecchio e il nuovo hash. Vedi Integrità dei file e persistenza.
  • Scansione malware, integrità del sistema: un /etc/ld.so.preload con voci è un rilevamento critico che ne mostra il contenuto; i processi presenti in /proc ma assenti da ps vengono segnalati come nascosti; vengono segnalati anche gli eseguibili in /tmp e /dev/shm e i binari di sistema cambiati da quando il loro pacchetto è stato installato (dpkg -V, rpm -Va). Vedi Malware.
  • La stessa sorveglianza copre la persistenza che di solito l'accompagna: crontab, unità systemd, authorized_keys e sudoers.

Limiti: le impronte vengono prese all'avvio dell'agent, quindi la sorveglianza dell'integrità segnala le modifiche a un file che esisteva in quel momento; un /etc/ld.so.preload che compare dopo, su un server che non ne aveva, lo trova la scansione malware. Le scansioni girano secondo la pianificazione che imposti (le scansioni automatiche sono disattivate di default) o quando premi **Scansiona ora**. Un rootkit caricato come modulo del kernel può nascondersi anche a /proc, e InfraFence non ha un rilevamento dedicato. InfraFence non cancella mai /etc/ld.so.preload né la libreria: la pulizia e la decisione di reinstallare restano tue.

Domande

/etc/ld.so.preload è sempre malevolo?
No, ma è raro. Un server normale non ce l'ha. Alcuni strumenti legittimi lo usano, come il logger di comandi Snoopy, e arrivano da un pacchetto che hai installato tu: dpkg -S o rpm -qf sulla libreria te lo dice.
Basta cancellare il file?
Ferma l'occultamento per ogni nuovo programma, ed è per questo che è il primo passo. Non rimuove ciò che l'attaccante ha fatto con root: persistenza, altre backdoor, segreti rubati. Per quello servono il resto della pulizia, o una reinstallazione.
rkhunter e chkrootkit lo trovano?
Controllano le librerie precaricate e i kit noti, e vale la pena eseguirli. Sono script che chiamano gli strumenti del sistema, quindi su un sistema infetto possono ricevere la stessa vista nascosta. Eseguili da un sistema di rescue per un risultato su cui contare.

Provalo gratis su 1 server

Starter è gratuito per un server, con protezione completa e blocco automatico. Senza carta di credito.

Installa l'agent come root, con il tuo token al posto di <TOKEN>:

curl -fsSL https://github.com/infrafence/infrafence-agent/releases/latest/download/install.sh | sudo bash -s -- --token <TOKEN>

Il token si crea nella dashboard, in Server › Aggiungi server.