Il blog sulla sicurezza di FireAI

Di FireAI Security & Research Team · Pubblicato

Caccia alla persistenza su macOS: LaunchAgent, elementi di accesso e attività in background

Caccia alla persistenza su macOS: LaunchAgent, elementi di accesso e attività in background

"Persistenza" è il termine di sicurezza per un problema specifico: come fa il codice eseguito una volta a essere eseguito nuovamente, automaticamente, dopo un riavvio o un accesso, senza che nessuno lo riavvii manualmente? macOS offre al software legittimo molti modi approvati per fare esattamente questo (un controllo degli aggiornamenti, un client di sincronizzazione della barra dei menu, un aiuto per il driver della stampante) e ognuno di questi meccanismi è ugualmente disponibile per qualcosa che preferiresti non eseguire affatto. Questo è un tour dei luoghi reali in cui cercare, con i comandi reali e un resoconto onesto di dove uno strumento focalizzato sulla rete come FireAI rientra e non appartiene a quella foto.

LaunchAgents e LaunchDaemons: i due grandi

macOS avvia quasi tutto tramite launchd, guidato dall'elenco delle proprietà (.plist) file in un numero limitato di directory conosciute. La tecnica T1543.001 di MITRE ATT&CK descrive chiaramente il meccanismo: all'accesso, un processo launchd per utente carica i plist dalle directory LaunchAgents dell'utente e del sistema e un plist con RunAtLoad impostato su true viene eseguito automaticamente nel momento in cui viene caricato: non sono necessarie ulteriori azioni da parte di chiunque lo abbia inserito lì. La tecnica elenca le tre posizioni che contano: /System/Library/LaunchAgents, /Library/LaunchAgents e ~/Library/LaunchAgents. MITRE nota qualcosa che vale la pena ricordare mentre si scorre un elenco di questi file: gli agenti installati per la persistenza sono spesso "camuffati[d]... utilizzando nomi che ricordano sistemi operativi o componenti software legittimi" - il file che assomiglia a com.apple.something.plist merita una seconda occhiata proprio perché sta cercando di non ottenerne uno.

I LaunchDaemons, coperti dalla tecnica correlata T1543.004, sono la versione a livello di sistema, senza necessità di login: vengono eseguiti come root, a partire dall'avvio, da /System/Library/LaunchDaemons/ o /Library/LaunchDaemons/. Poiché installarne uno lì richiede privilegi amministrativi fin dall'inizio, MITRE inquadra il percorso del demone come un modo per convertire un punto d'appoggio privilegiato iniziale in qualcosa che sopravvive al riavvio, funzionando con accesso a livello di root da quel momento in poi - che è anche il motivo per cui un nuovo file sconosciuto che appare in /Library/LaunchDaemons è un segnale più pesante di uno che appare nella cartella LaunchAgents di un utente.

Terminale: elenca ciò che è effettivamente registrato
ls -la ~/Library/LaunchAgents /Library/LaunchAgents /Library/LaunchDaemons
# compare this list against what you remember installing; anything you don't
# recognise is worth reading with: plutil -p /path/to/the.plist

Un file esistente su disco e un lavoro effettivamente caricato sono due domande diverse e launchctl print risponde alla seconda. La sua pagina man lo descrive come la stampa di "informazioni sul servizio o dominio specificato" - puntato su un dominio come system/ o gui/501/ (501 è l'UID di un utente), elenca tutti i servizi e gli endpoint attualmente caricati in quel contesto, più lo stato di ciascuno:

Terminale: cosa è effettivamente caricato in questo momento
launchctl print gui/$(id -u)
# example output, trimmed — a real run lists every loaded agent for your session
	"com.apple.someAgent" => {
		active count = 1
		path = /Library/LaunchAgents/com.apple.someAgent.plist
		state = running
	}

Elementi di accesso e gestione delle attività in background

La superficie rivolta all'utente per gran parte di questo è il riquadro Elementi di accesso delle Impostazioni di sistema e vale la pena controllarlo con i propri occhi, non solo con la riga di comando. La guida di supporto di Apple lo descrive direttamente: puoi "scegliere elementi di accesso che si aprono automaticamente quando accedi", aggiungerli o rimuoverli lì e consentire o negare separatamente le app che "eseguono attività quando l'app non è aperta, come il controllo degli aggiornamenti software o la sincronizzazione dei dati" - la seconda categoria copre gli aiutanti in background che non sono elementi di accesso completi ma vengono comunque eseguiti incustoditi.

A partire da macOS Ventura, il sistema sotto quel riquadro delle impostazioni è comunemente chiamato Background Task Management (BTM) nella comunità della sicurezza: un servizio che tiene traccia di ogni agente di lancio, demone di lancio ed elemento di accesso mentre si registra, che è ciò che consente alle Impostazioni di sistema di mostrarti un elenco live e centralizzato invece di dover andare a caccia manualmente attraverso tre directory plist. Esiste uno strumento da riga di comando non documentato, sfltool, che alcuni ricercatori utilizzano per interrogare il database in modo più diretto con sfltool dumpbtm: Apple non fornisce alcuna pagina man e non è garantito che il suo formato di output rimanga stabile, quindi trattalo come una curiosità di ricerca da provare sul tuo computer piuttosto che qualcosa su cui costruire un flusso di lavoro. Il modo stabile e supportato per visualizzare le stesse informazioni è ancora il riquadro Elementi di accesso in Impostazioni di sistema o launchctl print per lo stato attivo di un lavoro specifico.

cron: più vecchio, più silenzioso, ancora lì

launchd è stato lo scheduler preferito di Apple per molto tempo, ma il vecchio demone Unix cron viene ancora fornito ed esegue ancora qualsiasi cosa pianificata al suo interno. La pagina man di crontab descrive direttamente il formato del file: ogni riga ha cinque campi ora/data — minuto, ora, giorno del mese, mese, giorno della settimana — seguiti dal comando da eseguire, con @reboot e stringhe abbreviate simili disponibili al posto dei cinque campi su alcuni sistemi. crontab -l, secondo la pagina man crontab(1), "Visualizza il crontab corrente sull'output standard" per l'utente corrente:

Terminale: controlla il tuo crontab e quello di root
crontab -l
sudo crontab -l -u root

Un risultato vuoto per entrambi è normale oggi sulla maggior parte dei Mac: questo è esattamente il motivo per cui qualsiasi cosa lì dentro merita attenzione. cron non è affascinante e viene controllato raramente, motivo per cui viene ancora visualizzato come posizione di persistenza di riserva negli resoconti degli incidenti.

Profili di configurazione: persistenza con traccia cartacea

Un profilo di configurazione può installare un LaunchDaemon, concedere autorizzazioni sulla privacy o inviare impostazioni a un parco di Mac: legittimamente, è così che funziona MDM (gestione dei dispositivi mobili). Illegittimamente, un profilo è un modo documentato per apportare modifiche senza toccare direttamente un file plist. Lo strumento da riga di comando profiles elenca ciò che è installato: profiles list mostra i profili installati e, come nota la pagina man, eseguirlo come root con -all "elencherà tutti i profili di configurazione sul sistema" anziché solo quelli dell'utente corrente.

Terminale: ogni profilo di configurazione sul Mac
sudo profiles list -all
sudo profiles show -all

Un Mac personale senza registrazione MDM generalmente non dovrebbe averne nessuno o solo quelli installati deliberatamente (una configurazione VPN, un profilo di lavoro). Vale la pena esaminare un profilo che non ricordi di aver installato prima di rimuoverlo, poiché profiles supporta anche la rimozione con protezione tramite password esattamente per quel passaggio.

Plugin di autorizzazione e coda lunga

Oltre ai quattro grandi di cui sopra, c'è una lunga coda di meccanismi più piccoli e più vecchi: servizio di directory e plug-in di autorizzazione, importatori Spotlight, generatori QuickLook, plug-in del riquadro Dock e file di avvio della shell che vengono eseguiti ogni volta che si apre una nuova sessione di terminale. È qui che uno strumento appositamente creato guadagna il suo posto rispetto al controllo manuale. KnockKnock di Objective-See, ad esempio, enumera più di venti categorie di posizioni di persistenza in un unico passaggio - inclusi agenti di lancio e demoni, elementi di accesso, estensioni del browser, processi cron, estensioni del kernel e di sistema e plug-in di servizi di directory e di autorizzazione - e mostra lo stato di firma del codice di ciò che trova in ciascuno di essi. Il suo compagno, BlockBlock, prende lo stesso elenco di posizioni e le osserva continuamente, avvisando nel momento in cui si registra qualcosa di nuovo; secondo la sua stessa descrizione, "monitora le posizioni di persistenza comuni e avvisa ogni volta che viene aggiunto un nuovo componente persistente", mostrando il processo responsabile, il suo stato di firma e consentendoti di consentire o bloccare sul posto.

File di avvio della shell: il silenzioso problema di tutto

Un'altra posizione che merita uno sguardo diretto, poiché non necessita di plist né di installazione privilegiata: i file di configurazione della shell. ~/.zshrc, ~/.zprofile e ~/.bash_profile vengono eseguiti ogni volta che si apre una nuova sessione di terminale corrispondente e una singola riga aggiunta - reindirizzamento a uno script, esportazione di un PATH dirottato, avvio di un processo in background - è sufficiente per ristabilire un punto d'appoggio ogni volta che si apre Terminale, senza nulla da caricare in launchd e nulla da mostrare per launchctl print. KnockKnock di Objective-See include esattamente questa categoria nella sua scansione, elencata insieme agli agenti di lancio e agli elementi di accesso come file di configurazione della shell, per lo stesso motivo per cui appartiene a questo articolo: è abbastanza comune e abbastanza poco affascinante da valere la pena di verificarlo piuttosto che dare per scontato.

Terminale: una lettura veloce, non un sostituto della lettura effettiva
cat -A ~/.zshrc ~/.zprofile ~/.bash_profile 2>/dev/null | less
# -A shows non-printing characters, which surfaces anything hidden with
# trailing whitespace or a carriage return trying to push it off-screen

Dove FireAI si adatta e dove deliberatamente no

Per essere diretti al riguardo: FireAI non esegue la scansione di /Library/LaunchDaemons, non legge i file plist e non tenta di rilevare un nuovo elemento di accesso o profilo di configurazione. Si tratta di una disciplina distinta da ciò che fa FireAI e gli strumenti creati appositamente per essa, tra cui KnockKnock e BlockBlock, svolgono già bene questo lavoro. Ciò che FireAI osserva è il passaggio che viene dopo la persistenza, e di cui ognuno di questi meccanismi prima o poi ha bisogno per essere utile a chi lo ha installato: una connessione di rete. Un LaunchAgent che funziona silenziosamente a ogni accesso ma non comunica mai con la rete è, dal punto di vista di un firewall di rete, invisibile e, in pratica, molto meno utile per un utente malintenzionato. Nel momento in cui apre un socket, le regole per-app di FireAI si applicano ad esso come a qualsiasi altro processo: un binario sconosciuto, firmato o non firmato, che effettua la sua prima connessione attiva un prompt, con il ragionamento del modello sul dispositivo mostrato in un linguaggio semplice, e ogni decisione è visibile, annullabile ed esportabile successivamente come regola di testo.

Il modo onesto di mettere insieme le due discipline: controllare le posizioni in questo articolo secondo un programma che corrisponda alla propria tolleranza al rischio (mensile è ragionevole per la maggior parte delle persone, settimanalmente se si installano molti software di terze parti) e lasciare che uno strumento di rete si occupi del carico nel mezzo, partendo dal presupposto che tutto ciò che persiste in silenzio alla fine dovrà parlare per raggiungere chiunque a cui risponda.

Il ruolo di FireAI e di HisnLabs

FireAI does not scan for persistence — that is a different job, and tools like KnockKnock and BlockBlock already do it well; what FireAI watches is what that persisted code does the moment it opens a socket, which is the step every one of these mechanisms eventually has to take to be useful to whoever installed it.

FireAI è il prodotto di HisnLabs: un firewall con IA che funziona direttamente sul Mac. Mostra in linguaggio chiaro ogni connessione che le tue app effettuano e ti lascia decidere cosa esce dal tuo Mac — la sua IA lavora in locale, quindi il tuo traffico non viene mai inviato a noi né a nessun altro. Il team di ricerca sulla sicurezza di HisnLabs è quello che mantiene affidabili queste decisioni: cataloga quali domini sono semplice telemetria e quali un servizio reale, traccia il Paese e la rete dietro una connessione e addestra il modello locale (la funzione Autopilot) su schemi di traffico reali, senza che nulla lasci il tuo Mac.

Puoi leggere le scelte tecniche che ci stanno dietro, oppure provare FireAI per 17 giorni, su FireAI, di HisnLabs.

Fonti