InfraFenceInfraFence

Live Security Operations

Inizia

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.

Qualsiasi distribuzione
ps -eo pid,user,%cpu,etime,args --sort=-%cpu | head -n 15
  • Nomi: xmrig e 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, redis o postgres è 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:

Qualsiasi distribuzione
sudo ls -l /proc/PID/exe /proc/PID/cwd
sudo tr '\0' ' ' < /proc/PID/cmdline; echo
systemctl status PID

Un binario che mostra (deleted), o che gira da /tmp, /var/tmp o /dev/shm, è un segnale forte. Questo elenca tutti questi processi insieme:

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

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

Connessioni 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:

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

I file di configurazione dei miner contengono di solito l'URL di un pool. Questo li cerca nei posti abituali:

Qualsiasi distribuzione
sudo grep -rIl -E 'stratum\+(tcp|ssl)://|"pools"|donate-level' /tmp /var/tmp /dev/shm /root /home /var/www /etc 2>/dev/null

Cosa 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.

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

Poi i timer systemd e i file di unità modificati negli ultimi 30 giorni:

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

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

Infine 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.

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

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.

Qualsiasi distribuzione con nftables
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 drop

Tieni 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.

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

Prima 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.

Qualsiasi distribuzione
sudo kill -STOP PID
ps -o pid,ppid,user,args -p PID
sudo kill -9 PID

Attenzione: 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):

Qualsiasi distribuzione
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.d che non hai creato tu.
  • SSH: cancella da ogni authorized_keys le chiavi che non riconosci.
  • Account: blocca o cancella gli utenti che non hai creato (sudo usermod -L NOME), e controlla /etc/sudoers e /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:

Qualsiasi distribuzione
sudo lsattr /path/to/file
sudo chattr -i -a /path/to/file
sudo rm /path/to/file

Se /etc/ld.so.preload nomina una libreria che non conosci, spostalo (è raro che un software legittimo lo usi) e cancella la libreria indicata:

Qualsiasi distribuzione
sudo mv /etc/ld.so.preload /root/evidence/ld.so.preload
sudo ldconfig

Riavvia, 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:

Qualsiasi distribuzione
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.
Accessi SSH
last -i -n 50
sudo journalctl --since "14 days ago" | grep -E "Accepted (password|publickey)"
Log del web server
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 50

E 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.

Qualsiasi distribuzione
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 ogni authorized_keys sono 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 ps e 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.