Ottenere l’accesso è metà del lavoro; l’altra metà consiste nel non perderlo. Per questo quasi tutto il software dannoso automatizzato si assicura anzitutto di essere riavviato: dopo un riavvio, dopo la cancellazione del file, dopo un cambio di password. Da qui la storia nota: «abbiamo ripulito e due giorni dopo è tornato».

I posti in cui questo si organizza non sono molti, e tutti si verificano in pochi minuti. Ecco il giro completo, in ordine.

1. Le chiavi SSH

Il ritorno più semplice: una riga in authorized_keys sopravvive a un cambio di password, a un aggiornamento del sistema e a un riavvio.

sudo find /home /root -name authorized_keys -exec ls -l {} \; -exec cat {} \;

Ogni riga è l’accesso permanente di qualcuno. Se non può dire di chi, la consideri altrui. Guardi anche il commento a fine riga: è testo libero, e una corrispondenza con il suo nome non dimostra nulla.

2. Le attività cron di tutti gli utenti

Non va verificata solo la sua crontab:

for u in $(cut -f1 -d: /etc/passwd); do echo "== $u"; sudo crontab -u "$u" -l 2>/dev/null; done
sudo ls -la /etc/cron.d/ /etc/cron.hourly/ /etc/cron.daily/
sudo cat /etc/crontab

Che cosa cercare: righe con @reboot, comandi lunghi codificati, chiamate a curl o wget reindirizzate a un interprete, tutto ciò che viene avviato da /tmp, /dev/shm o /var/tmp. Da quelle cartelle non parte nulla di regolare.

3. Timer e servizi di systemd

L’equivalente moderno di cron, e si verifica assai meno spesso:

systemctl list-timers --all
systemctl list-units --type=service --state=running
sudo ls -la /etc/systemd/system/ /run/systemd/system/

A parte, i servizi utente, che girano senza privilegi di root e non compaiono nell’elenco generale:

systemctl --user list-units --type=service
sudo ls -la /home/*/.config/systemd/user/

Un dettaglio in più: se per un utente è attivata la persistenza (loginctl enable-linger), i suoi servizi girano senza sessione attiva. Si verifica con loginctl list-users.

4. I file di avvio della shell

Il codice aggiunto in fondo a un file di avvio della shell viene eseguito a ogni accesso:

sudo tail -5 /root/.bashrc /root/.profile /home/*/.bashrc /home/*/.profile
sudo ls -la /etc/profile.d/

Guardi proprio la fine del file: è lì che si aggiunge per non dare nell’occhio a un’occhiata rapida.

5. ld.so.preload

Un file che costringe il sistema a caricare una data libreria in ogni processo avviato. In condizioni normali non viene mai creato:

ls -l /etc/ld.so.preload

La sua presenza è praticamente un segno inequivocabile di compromissione grave, e una libreria simile di solito nasconde sia file sia processi sia connessioni di rete. Nulla di ciò che vedrà poi su quella macchina merita fiducia.

6. I gancio del gestore di pacchetti

Un metodo che si considera di rado: apt può eseguire comandi prima e dopo ogni operazione sui pacchetti.

sudo ls -la /etc/apt/apt.conf.d/
sudo grep -r 'DPkg::Pre-Invoke\|DPkg::Post-Invoke\|APT::Update' /etc/apt/apt.conf.d/

Un gancio simile scatta a ogni installazione di aggiornamenti, cioè con regolarità e come root.

7. Il messaggio del giorno su Ubuntu

La cartella /etc/update-motd.d/ contiene script eseguibili che girano a ogni accesso SSH e compongono il testo di benvenuto. Il posto è comodo proprio perché sembra parte del sistema:

sudo ls -la /etc/update-motd.d/

8. Le attività differite di at

sudo atq
sudo ls -la /var/spool/cron/atjobs/ 2>/dev/null

Un meccanismo vecchio e poco usato, e per questo il meno verificato di tutti.

Che fare se salta fuori qualcosa

Il primo impulso è cancellare subito il ritrovamento. È un errore: con esso sparisce l’informazione su come sia arrivato lì, e senza risposta a quella domanda tutto si ripeterà.

  1. Conservare una copia del file o dell’attività e la sua ora di modifica.
  2. Con quell’ora, guardare nei registri del server web e in auth.log che cosa accadeva nello stesso minuto. Lì di solito sta il punto d’ingresso.
  3. Verificare tutti e otto i posti dell’elenco, e non solo quello in cui è saltato fuori qualcosa. Una porta di servizio non viene quasi mai lasciata in un solo esemplare.
  4. Solo dopo ripulire e chiudere la vulnerabilità stessa.

Sapere com’è la normalità

La difficoltà principale di questa verifica non sono i comandi, ma il fatto che una riga sconosciuta in un elenco di attività non sembra sospetta se non ricorda com’era l’elenco prima. Su un server configurato da qualcun altro, o configurato un anno fa, distinguere il proprio dall’altrui è quasi impossibile.

Da qui la conclusione pratica: prendere oggi uno snapshot dello stato attuale ha senso, finché il server è in ordine. L’elenco delle attività cron, dei timer, delle chiavi e dei servizi di una macchina sana è il riferimento con cui si confronterà poi. Raccolto e conservato con uno storico, trasforma la ricerca di una porta di servizio da esercizio di più ore in un confronto fra due elenchi. Come appare lo mostrano le pagine dimostrative qui sotto.