Skip to main content
  1. Blog/

Cancellato. Ma non abbastanza.

Alessio Barnini
Author
Alessio Barnini
Table of Contents

TL;DR
  • testuser compare all'01:14, tenta l'escalation, poi viene cancellato alle 04:47
  • auth.log registra ogni evento: creazione, tre sudo falliti, disconnessione
  • find / -uid 1001 2>/dev/null trova i file rimasti anche dopo userdel
  • Cancellare un utente non cancella la sua storia - cancella solo il nome
$ history
  • grep -E "useradd|userdel" /var/log/auth.log
  • grep "testuser" /var/log/auth.log
  • last testuser
  • find / -uid 1001 2>/dev/null
  • cat /home/testuser/.bash_history
  • journalctl --since "2026-03-25 04:40"

Utente cancellato - post-mortem auth.log

Sono le 09:23. Il collega di guardia ha lasciato un messaggio su Slack prima di staccare il turno.

"Ho visto una cosa strana stanotte. C'era un utente testuser che non ricordo di aver creato. L'ho cancellato, ma magari vale la pena guardare."

Apro il terminale. getent passwd testuser non restituisce nulla - l'utente non esiste più. Ma l'assenza di un account non è l'assenza di una storia.


La cancellazione
#

Prima di tutto voglio sapere quando è arrivato e quando è sparito.

grep -E "useradd|userdel|new user|delete user" /var/log/auth.log
# output simulato
Mar 25 01:14:32 prod-server useradd[2847]: new user: name=testuser, UID=1001, GID=1001, home=/home/testuser, shell=/bin/bash
Mar 25 04:47:11 prod-server userdel[3912]: delete user 'testuser'
Mar 25 04:47:11 prod-server userdel[3912]: removed group 'testuser' owned by 'testuser'

Creato all'01:14. Cancellato alle 04:47. Tre ore e mezza di attività.

Noto subito che il userdel non ha il flag -r. La home /home/testuser potrebbe essere ancora sul disco.

ls -la /home/testuser/
# output simulato
drwxr-xr-x 3 1001 1001 4096 Mar 25 04:44 .
drwxr-xr-x 8 root root 4096 Mar 25 01:14 ..
-rw------- 1 1001 1001  847 Mar 25 04:44 .bash_history
-rw-r--r-- 1 1001 1001  220 Mar 25 01:14 .bash_logout
-rw-r--r-- 1 1001 1001 3526 Mar 25 01:14 .bashrc

Esiste ancora. Il .bash_history è stato scritto alle 04:44 - tre minuti prima della cancellazione. Qualcuno ha usato la shell attivamente fino all'ultimo.


Le sessioni
#

last testuser
# output simulato
testuser pts/1  192.168.64.47  Tue Mar 25 01:15 - 04:44  (03:29)

Login da 192.168.64.47 - un IP interno. Non un attaccante esterno: qualcuno già dentro la rete, o una macchina compromessa.


Il tentativo di escalation
#

Leggo tutto quello che auth.log sa di questo account.

grep "testuser" /var/log/auth.log
# output simulato
Mar 25 01:14:32 prod-server useradd[2847]: new user: name=testuser, ...
Mar 25 01:15:08 prod-server sshd[2891]: Accepted password for testuser from 192.168.64.47 port 54219 ssh2
Mar 25 01:15:08 prod-server sshd[2891]: pam_unix(sshd:session): session opened for user testuser(uid=1001) by (uid=0)
Mar 25 02:03:41 prod-server sudo: testuser : user NOT in sudoers ; TTY=pts/1 ; PWD=/home/testuser ; COMMAND=/usr/bin/id
Mar 25 02:03:55 prod-server sudo: testuser : user NOT in sudoers ; TTY=pts/1 ; PWD=/home/testuser ; COMMAND=/bin/bash
Mar 25 02:04:17 prod-server sudo: testuser : user NOT in sudoers ; TTY=pts/1 ; PWD=/usr/bin ; COMMAND=/usr/bin/python3 -c import os; os.setuid(0); os.system('/bin/bash')
Mar 25 04:44:12 prod-server sshd[3901]: Disconnected from user testuser 192.168.64.47 port 54219

Tre tentativi sudo in 36 secondi. Il terzo è il più istruttivo: python3 -c "import os; os.setuid(0); os.system('/bin/bash')" - il classico tentativo di usare un interprete per bypassare i controlli shell. Qui non funziona perché sudo è bloccato, ma la tecnica mostra che chi era dietro la tastiera sapeva quello che faceva.


I file rimasti
#

L'account è cancellato ma i file sul disco appartengono ancora all'UID 1001 - un numero senza più un nome. Questi si chiamano orphaned file: residui che sopravvivono alla cancellazione dell'utente.

find / -uid 1001 2>/dev/null
# output simulato
/home/testuser
/home/testuser/.bash_history
/home/testuser/.bash_logout
/home/testuser/.bashrc
/tmp/.priv_check.sh
/tmp/.out

Due file in /tmp con il punto iniziale per nasconderli da un ls normale. Non erano nella home.

cat /tmp/.priv_check.sh
# output simulato
#!/bin/bash
find / -perm -4000 -type f 2>/dev/null
sudo -l 2>/dev/null
id
cat /etc/sudoers 2>/dev/null

Uno script di ricognizione dei privilegi. Lo ha scritto o scaricato, eseguito, e dimenticato in /tmp.

cat /tmp/.out
# output simulato
/usr/bin/sudo
/usr/bin/newgrp
/usr/bin/passwd
/usr/bin/su
/usr/bin/mount
sudo: a password is required
uid=1001(testuser) gid=1001(testuser) groups=1001(testuser)
cat: /etc/sudoers: Permission denied

L'output dell'esecuzione. Nessuna via: python3 senza SUID, sudo bloccato, sudoers inaccessibile. Ha cercato, non ha trovato, e si è fermato.


Il .bash_history
#

cat /home/testuser/.bash_history
# output simulato
id
whoami
uname -a
cat /etc/passwd
cat /etc/shadow
ls -la /usr/bin/python3
stat /usr/bin/python3
find / -perm -4000 -type f 2>/dev/null
sudo id
sudo /bin/bash
sudo python3 -c "import os; os.setuid(0); os.system('/bin/bash')"
cat /etc/sudoers
bash .priv_check.sh
ls /root
ls /var/backups
cat /var/backups/passwd.bak
exit

La sequenza è leggibile: identificazione del sistema → ricognizione SUID → tentativi sudo → esplorazione a mano → rinuncia. Tutto in ordine cronologico, tutto tracciato.


Chi ha cancellato l'account
#

Il log dice userdel[3912] ma non dice chi ha avviato il processo. Serve il journal - più resistente di auth.log alla manomissione.

journalctl --since "2026-03-25 04:40" --until "2026-03-25 04:50" | grep -i "userdel\|testuser"
# output simulato
Mar 25 04:46:58 prod-server sudo[3911]: barno : TTY=pts/0 ; PWD=/root ; USER=root ; COMMAND=/usr/sbin/userdel testuser

barno - il collega di turno. Ha riconosciuto l'anomalia, ma invece di preservarla per l'analisi l'ha rimossa. Con buone intenzioni e procedura sbagliata.


Dietro le quinte
#

Timeline e kill chain - ricostruzione forense

gantt
    dateFormat HH:mm
    axisFormat %H:%M
    section Attività testuser
    Creazione account    :01:14, 1m
    Login SSH            :01:15, 1m
    Ricognizione sistema :crit, 01:15, 49m
    Tentativi sudo       :crit, 02:03, 2m
    Esplorazione manuale :02:05, 2h39m
    Disconnessione       :04:44, 1m
    section Risposta
    Cancellazione account :04:47, 1m

Kill chain
#

graph LR
    Creazione["Creazione\ntestuser UID 1001"] --> Login["SSH login\n192.168.64.47"]
    Login --> Recon["Ricognizione\nSUID + sudoers"]
    Recon --> Escalation["3x sudo\nfallito"]
    Escalation --> Esplora["Esplorazione\n/root, /var/backups"]
    Esplora --> Exit["Disconnessione\nexit"]
    Exit --> Cleanup["userdel testuser\nda barno"]
    Cleanup --> Residui["Orphaned file\n/tmp/.priv_check.sh"]

Comandi chiave
#

Tutti gli eventi di un utente in auth.log:

grep "testuser" /var/log/auth.log

Creazione e cancellazione utenti:

grep -E "useradd|userdel|new user|delete user" /var/log/auth.log

Orphaned file - UID senza account:

find / -uid 1001 2>/dev/null    # UID specifico
find / -nouser 2>/dev/null      # tutti i file senza proprietario

Sessioni di login (da wtmp):

last testuser

Journal - più affidabile di auth.log:

journalctl --since "2026-03-25 01:00" --until "2026-03-25 05:00" | grep testuser

auth.log è un file di testo modificabile da root - può essere svuotato silenziosamente con > /var/log/auth.log. Il journal usa Forward Secure Sealing (FSS): ogni blocco è firmato crittograficamente, le modifiche sono rilevabili. Per incidenti seri, il journal è la fonte primaria.

IoC
#

TipoValoreContestoMITRE ATT&CK
Utentetestuser UID 1001Account creato e cancellato nella stessa notteT1136.001
IP192.168.64.47Origine connessione SSH internaT1021.004
File/tmp/.priv_check.shScript ricognizione privilegiT1087.001
File/tmp/.outOutput ricognizione - lasciato sul discoT1087.001
Tecnicasudo python3 -c "import os; os.setuid(0)..."Tentativo escalation via interpreteT1548.003
Tecnicauserdel senza -rCancellazione incompleta - home e /tmp intattiT1070.001

Checklist post-mortem
#

  • Identificare la macchina 192.168.64.47 e verificarne lo stato
  • Verificare come è stata ottenuta la password di testuser
  • Cercare accessi dallo stesso IP nelle settimane precedenti
  • Verificare accesso a /var/backups/passwd.bak - era nel bash_history
  • Abilitare log forwarding esterno - auth.log locale è alterabile da root
  • Configurare alert SIEM su eventi useradd e userdel

exit 0
#

Cancellare un account sospetto non è incident response. È contaminare la scena.

Quello che ha salvato questa analisi è stata la combinazione di tre errori dell'attaccante: userdel senza -r, file lasciati in /tmp, e auth.log ancora intatto. In un sistema con log forwarding esterno non avremmo avuto bisogno di fortuna per ricostruire la timeline.

La prossima volta che trovi un utente sospetto: isolalo, non cancellarlo. Il nome si recupera in tre secondi. I log in memoria, la connessione TCP attiva, i file aperti - quelli no.


Scarica il PDF

Comandi usati: grep · find · last Concetti correlati: iam · observability Approfondimento tecnico: auth.log - log di autenticazione · PAM - Pluggable Authentication Modules

Related