Come trovare e rimuovere un crypto miner dal server
Ultimo aggiornamento:
Un crypto miner è la cosa più comune che si trova su un server Linux compromesso. Usa tutta la CPU che può per minare Monero o un'altra moneta per qualcun altro, e il primo segnale è spesso un sito lento, una ventola al massimo, una fattura per crediti CPU o un'email di abuso dal provider.
Il miner in sé è la parte facile. Conta quello che l'ha fatto entrare e quello che lo riporta: un cron, un'unità systemd, una chiave SSH, una libreria precaricata in ogni processo. Procedi in quest'ordine: trovare, isolare, rimuovere, trovare il punto d'ingresso, mettere in sicurezza. I comandi sono per Debian e Ubuntu e per la famiglia RHEL; PID è l'ID del processo che trovi al passo 1.
Riconoscere il miner
Parti da cosa usa la CPU. Un miner di solito occupa un processo al 100% per core, attivo da giorni.
ps -eo pid,user,%cpu,etime,args --sort=-%cpu | head -n 15- Nomi:
xmrige le sue varianti, oppure nomi scelti per sembrare innocui:kdevtmpfsi,kinsing,kworkerds, un[kthreadd]scritto a mano, una stringa casuale. - Un thread del kernel appare tra parentesi quadre e non ha un binario: un nome tra parentesi con un percorso dietro è un falso.
- L'utente: un miner che gira come
www-data,apache,nginx,redisopostgresè entrato da quel servizio.
Per un PID sospetto guarda il suo binario, la directory di lavoro, la riga di comando completa e quale unità systemd l'ha avviato:
sudo ls -l /proc/PID/exe /proc/PID/cwd
sudo tr '\0' ' ' < /proc/PID/cmdline; echo
systemctl status PIDUn binario che mostra (deleted), o che gira da /tmp, /var/tmp o /dev/shm, è un segnale forte. Questo elenca tutti questi processi insieme:
sudo ls -l /proc/[0-9]*/exe 2>/dev/null | grep -E '\(deleted\)|/tmp/|/var/tmp/|/dev/shm/'Quando top non mostra niente: ld.so.preload
Se il carico è alto ma nessun processo lo spiega, il miner può nascondersi dietro una libreria caricata in ogni programma tramite /etc/ld.so.preload. Quel file normalmente non esiste. Se c'è e nomina una libreria che non conosci, ps e top ti stanno mentendo.
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/nullConnessioni a un mining pool
I miner parlano con un pool con il protocollo stratum. Porte come 3333, 4444, 5555, 7777 e 14444 sono tipiche, ma i pool ascoltano anche su 443 e 80, quindi guarda anche le connessioni del processo stesso:
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 PIDI file di configurazione dei miner contengono di solito l'URL di un pool. Questo li cerca nei posti abituali:
sudo grep -rIl -E 'stratum\+(tcp|ssl)://|"pools"|donate-level' /tmp /var/tmp /dev/shm /root /home /var/www /etc 2>/dev/nullCosa lo fa ripartire
Cerca la persistenza prima di uccidere qualcosa, così sai cosa togliere. Prima cron: righe che scaricano con curl o wget, decodificano base64 o eseguono da /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/nullPoi i timer systemd e i file di unità modificati negli ultimi 30 giorni:
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"Poi chiavi SSH che non hai aggiunto tu, rc.local, i file di avvio della shell e account che non hai creato:
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/passwdInfine verifica che i binari del sistema non siano stati sostituiti. L'output elenca i file dei pacchetti il cui contenuto è cambiato; i file di configurazione sono esclusi.
sudo dpkg --verify | grep -v ' c /'sudo rpm -Va 2>/dev/null | grep -E '^..5' | grep -v ' c /'Isolarlo
Se il provider può fare uno snapshot del disco, fallo adesso: conserva le prove e una via di ritorno. Poi taglia il miner fuori dal suo pool. Sostituisci 198.51.100.23 con l'indirizzo del pool trovato al passo 1. Questa tabella nftables funziona su Debian, Ubuntu e famiglia RHEL accanto a ufw o firewalld, e sparisce al riavvio.
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 dropTieni una copia del binario e della sua riga di comando prima che venga cancellato. /proc/PID/exe funziona anche se il file su disco è già stato rimosso. Lo SHA-256 si può cercare nei database pubblici di malware.
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.binPrima congela il processo, così un watchdog non lo vede morire e non lo riavvia subito, guarda il processo padre, poi uccidilo. Se il padre è uno script o un secondo processo del miner, occupati anche di quello.
sudo kill -STOP PID
ps -o pid,ppid,user,args -p PID
sudo kill -9 PIDAttenzione: Considera noto ogni segreto presente sul server: chiavi SSH, password, password dei database e chiavi API in .env e nei file di configurazione. Cambiali da una macchina pulita, cominciando dagli account che raggiungono altri server.
Rimuoverlo con tutto quello che lo riporta
Togli ogni elemento di persistenza trovato al passo 1, poi i binari. Per un'unità systemd (sostituisci NAME):
sudo systemctl disable --now NAME.service
sudo rm /etc/systemd/system/NAME.service
sudo systemctl daemon-reload- Cron: cancella le righe con
sudo crontab -e -u UTENTE, e i file in/etc/cron.dche non hai creato tu. - SSH: cancella da ogni
authorized_keysle chiavi che non riconosci. - Account: blocca o cancella gli utenti che non hai creato (
sudo usermod -L NOME), e controlla/etc/sudoerse/etc/sudoers.d/. - Binari e file di configurazione del miner, ovunque li abbia trovati il passo 1.
Spesso i miner rendono immutabili i loro file, così rm fallisce con Operation not permitted anche da root. Controlla e togli prima gli attributi:
sudo lsattr /path/to/file
sudo chattr -i -a /path/to/file
sudo rm /path/to/fileSe /etc/ld.so.preload nomina una libreria che non conosci, spostalo (è raro che un software legittimo lo usi) e cancella la libreria indicata:
sudo mv /etc/ld.so.preload /root/evidence/ld.so.preload
sudo ldconfigRiavvia, poi ricontrolla la CPU dopo un'ora e il giorno dopo: un miner che torna vuol dire che un elemento di persistenza o il punto d'ingresso sono ancora lì.
Attenzione: Se il miner girava come root, se i binari di sistema sono cambiati o se è stato usato ld.so.preload, non puoi essere sicuro che il server sia pulito. Ricostruiscilo da un'immagine nuova e ripristina i dati da un backup precedente all'infezione, dopo averlo controllato. Pulire sul posto è ragionevole solo quando il miner girava come utente senza privilegi e non è cambiato niente fuori dai file di quell'utente.
Trovare da dove è entrato
Se non chiudi la via d'ingresso, il miner torna in pochi giorni. L'utente con cui girava e l'ora in cui sono stati creati i suoi file la indicano:
ps -o user,pid,lstart,args -p PID
sudo stat /path/to/miner- Gira come l'utente del web server: un plugin, un tema o un'applicazione vulnerabile, o un modulo di upload. Guarda i log web intorno all'ora in cui è comparso il file.
- Gira come
redis, o ha file creati da redis: Redis aperto su internet senza password. - Avviato da un container o da
dockerd: l'API di Docker esposta su 2375 o 2376. - Gira come root o come utente normale con un accesso poco prima: una password debole o una chiave SSH rubata.
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 50E i servizi che sono vie d'ingresso comuni quando ascoltano su tutte le interfacce: l'API di Docker, Redis, console web sulla 8080, Elasticsearch, MongoDB, Memcached.
sudo ss -tlnp | grep -E ':(2375|2376|6379|8080|9200|27017|11211)\b'Mettere in sicurezza il server dopo
- Chiudi il punto d'ingresso trovato: aggiorna o togli l'applicazione, lega Redis e i database a localhost con una password, non esporre mai l'API di Docker.
- SSH solo con chiavi e senza root: vedi Come bloccare gli attacchi brute force SSH.
- Installa gli aggiornamenti, attiva quelli di sicurezza automatici e il firewall: vedi Mettere in sicurezza un nuovo VPS: la checklist.
- Limita il traffico in uscita dove puoi: un web server raramente deve aprire connessioni verso porte qualsiasi.
- Da ora sorveglia l'uso della CPU, le connessioni in uscita e le modifiche a cron, systemd e chiavi SSH, così il prossimo si scopre in minuti e non in settimane.
Come InfraFence rileva un crypto miner
Diversi rilevatori di InfraFence coprono i passi qui sopra, ognuno da un lato diverso:
- Rilevamento dei processi: un processo attivo il cui nome o la cui riga di comando corrisponde a un miner noto (xmrig, minerd, cpuminer e altri), a un URL stratum o a un pool noto viene segnalato come critico, con PID e riga di comando. Vengono segnalati anche reverse shell e script eseguiti da
/tmp. - Scansione malware: firme per crypto miner, web shell e backdoor nei tuoi siti, regole YARA aggiornate ogni giorno, e i binari di sistema confrontati con il database dei pacchetti (
dpkg -V/rpm -Va). - Uscita e DNS: connessioni verso indirizzi presenti nelle liste pubbliche di threat intelligence, e ogni query DNS collegata al programma che l'ha fatta.
- Integrità dei file:
/etc/ld.so.preload, i crontab, le unità systemd e ogniauthorized_keyssono registrati con un hash e sorvegliati, e ogni modifica genera subito un avviso. - Controlli di hardening che segnalano le vie d'ingresso abituali: database aperti su internet, software non aggiornato, SSH con password.
Il controllo dei processi confronta nomi e righe di comando: un miner rinominato che legge il pool da un file di configurazione non corrisponde, e resta agli altri rilevatori. La pulizia descritta in questa guida resta da fare a te.
Domande
- Posso semplicemente uccidere il processo?
- Tornerà. I miner installano un cron, un'unità systemd o una chiave SSH per ripartire, e il buco da cui sono entrati è ancora aperto. Togli la persistenza e chiudi il punto d'ingresso.
- Devo reinstallare il server?
- Se il miner girava come root, se i binari di sistema sono cambiati o se è stato usato
/etc/ld.so.preload, sì: non puoi dimostrare che il server è pulito. Se girava come utente senza privilegi e non è cambiato altro, una pulizia accurata può bastare. - Il provider dice che il server sta minando ma non vedo niente. Perché?
- Il miner può essere nascosto con
/etc/ld.so.preload, girare in un container, o partire da cron solo a certe ore. Controlla il file di preload,docker pse le connessioni che il server apre nel tempo.
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.
