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à.
- Conservare una copia del file o dell’attività e la sua ora di modifica.
- Con quell’ora, guardare nei registri del server web e in
auth.logche cosa accadeva nello stesso minuto. Lì di solito sta il punto d’ingresso. - 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.
- 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.