Fondamenti di macOS e Linux · Lezione 1 di 5
macOS: struttura, plist e account
12 min di lettura
Un Mac conserva la maggior parte della propria configurazione e gran parte dell'attività degli utenti in file ordinari: elenchi di proprietà, piccoli database e attributi estesi, distribuiti in una struttura di directory diversa da quelle di Windows e Linux. Questa lezione presenta le directory in cui opera un esaminatore, spiega come leggere gli elenchi di proprietà e gli attributi che macOS associa ai file scaricati e mostra dove il sistema registra versione, nomi, fuso orario, account e cronologia delle installazioni. Spiega inoltre perché sui Mac moderni si esegue generalmente un'acquisizione logica. La lezione 1.7 ha trattato i volumi APFS e la lezione 3.1 i formati temporali Apple; entrambe sono considerate prerequisiti.
La struttura delle directory
In macOS 10.15 Catalina e versioni successive, l'albero visibile combina il volume System di sola lettura e il volume Data (lezione 1.7). /etc, /var e /tmp sono collegamenti simbolici a /private/etc, /private/var e /private/tmp, quindi una raccolta di triage o un parser può mostrare entrambe le forme.
| Percorso | Contenuto | Note per l'esaminatore |
|---|---|---|
/System | Il sistema operativo, sul volume System sigillato | Di sola lettura; contiene SystemVersion.plist |
/Applications | Applicazioni installate dagli utenti e dall'App Store | Da Catalina, le app integrate di Apple si trovano in /System/Applications |
/Library | Impostazioni e file di supporto a livello di sistema per tutti gli utenti | Preferences, Application Support, Logs, elementi di avvio (lezione 6.5) |
/Users/<name> | Cartelle home | Desktop, Documents, Downloads e la cartella nascosta Library |
~/Library/Preferences | Impostazioni delle applicazioni per ciascun utente, un plist per app | Il nome corrisponde all'identificatore del bundle, ad esempio com.apple.finder.plist |
~/Library/Application Support | Dati e database per ciascuna app | Molti database di browser e chat (modulo 4) |
~/Library/Containers/<bundle-id> | Dati delle app in sandbox | Data/ rispecchia una cartella home, quindi le preferenze dell'app si trovano in Data/Library/Preferences |
~/Library/Group Containers/<group-id> | Dati condivisi dalle app di uno stesso sviluppatore | Ad esempio, group.com.apple.notes contiene il database di Note |
~/Library/Caches, ~/Library/Logs | Cache e log delle applicazioni per ciascun utente | Volatili, ma spesso trascurati |
/private/var/db | Database di sistema | Account locali (dslocal), receipts, .AppleSetupDone, archivi dei log unificati (diagnostics, uuidtext) |
/private/var/log | Log testuali | install.log, system.log |
/private/var/folders | Cartelle temporanee e di cache per ciascun utente | /private/var/folders/<2 chars>/<random>/ con sottocartelle T (temporanei), C (cache) e 0 |
/private/etc | Configurazione Unix | hosts, sudoers, il collegamento localtime |
Le app in sandbox (tutte le app dell'App Store e le app integrate come Safari nelle versioni attuali) conservano i propri dati nel rispettivo contenitore; occorre quindi cercare in tale posizione prima di concludere che un'app non abbia lasciato preferenze.
File nascosti e attributi estesi
Finder nasconde i nomi che iniziano con un punto e gli elementi contrassegnati con il flag BSD hidden (impostato con chflags hidden e visualizzato da ls -lO); ~/Library viene nascosta in questo modo. Gli strumenti forensi mostrano entrambe le categorie.
Gli attributi estesi (xattr) sono elementi di metadati dotati di un nome, memorizzati insieme a un file ma al di fuori del suo contenuto. xattr -l <file> ne elenca nomi e valori. Due sono rilevanti in quasi tutti i casi:
com.apple.quarantine: aggiunto ai file scaricati dalle app che supportano la quarantena (browser, client di posta e messaggistica, AirDrop). Il suo valore è una stringa di testoflags;timestamp;agent;UUID: quattro cifre esadecimali di flag, l'ora in secondi Unix esadecimali, il nome dell'applicazione che ha effettuato il download e un UUID che rimanda al database degli eventi di quarantena dell'utente~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2, che può contenere l'URL di download.com.apple.metadata:kMDItemWhereFroms: gli URL di origine di un download, solitamente l'URL del file e la pagina di provenienza. Il suo valore è un elenco di proprietà binario contenente un array di stringhe.
Gli attributi estesi esistono solo nei file system che li supportano, come APFS e HFS+. Quando un Mac copia un file su FAT32 o exFAT, macOS memorizza gli attributi in un file AppleDouble separato denominato ._<filename> (firma 00 05 16 07); i file ._ su un'unità USB mostrano quindi che un Mac vi ha scritto. La maggior parte delle altre operazioni di copia (caricamenti, molti strumenti di archiviazione, strumenti di copia che non conservano gli xattr neppure su file system che li supportano) li elimina senza avvisi. Eseguire l'acquisizione in un formato immagine o contenitore che conservi gli xattr, oppure registrarli con xattr -l prima della copia.
Elenchi di proprietà
Un elenco di proprietà (plist) serializza un albero di valori tipizzati: dizionari, array, stringhe, interi, reali, booleani, date e dati grezzi. Svolge il ruolo di una chiave del Registro di sistema, ma ogni plist è un file separato. Sono rilevanti tre forme:
| Forma | Come riconoscerla | Note |
|---|---|---|
| XML | Inizia con <?xml e un DOCTYPE plist | Date come testo ISO 8601, dati come Base64 |
| Binaria | I primi 8 byte sono bplist00 | La maggior parte dei plist di sistema e delle app; un trailer di 32 byte alla fine punta a una tabella degli offset |
| JSON | Inizia con { o [ | Un'opzione di esportazione di plutil; non può rappresentare date o dati, quindi le conversioni di plist che li contengono non riescono |
Su un Mac, plutil -p <file> visualizza qualsiasi plist in modo leggibile e plutil -convert xml1 -o out.xml <file> scrive una copia XML. Senza -o, plutil -convert riscrive il file nella posizione originale, quindi eseguirlo soltanto su copie di lavoro. Su Linux o Windows, plistlib di Python legge i plist XML e binari.
In un plist binario, ogni oggetto inizia con un byte marcatore: i quattro bit più significativi indicano il tipo e i quattro bit meno significativi una lunghezza o un codice di dimensione. 0x5n è una stringa ASCII di n caratteri, 0x6n una stringa UTF-16, 0x1n un intero, 0x23 un reale di 8 byte, 0x33 una data, 0x4n dati grezzi, 0x8n un riferimento UID, 0xAn un array e 0xDn un dizionario. Una data è un valore double big-endian di 8 byte espresso in Mac Absolute Time.
Sono comuni due forme di annidamento. Un valore data può a sua volta iniziare con bplist00: un plist all'interno di un plist che deve essere decodificato nuovamente. Inoltre, molte app serializzano gli oggetti con NSKeyedArchiver: il plist presenta le chiavi $archiver (valore NSKeyedArchiver), $version, $top e $objects, e i valori sono distribuiti nell'array $objects e collegati da riferimenti UID. Leggerli con un parser in grado di deserializzarli anziché mediante ispezione visiva.
Plist di sistema principali
| Domanda | File o percorso | Chiave |
|---|---|---|
| Versione e build di macOS | /System/Library/CoreServices/SystemVersion.plist | ProductVersion, ProductBuildVersion |
| Nomi del computer | /Library/Preferences/SystemConfiguration/preferences.plist | System/System/ComputerName, System/System/HostName (se impostata), System/Network/HostNames/LocalHostName |
| Fuso orario | /private/etc/localtime (collegamento simbolico) | Destinazione del collegamento, ad esempio /var/db/timezone/zoneinfo/Europe/Berlin |
| Città scelta per il fuso orario | /Library/Preferences/.GlobalPreferences.plist | com.apple.TimeZonePref.Last_Selected_City |
| Ultimo utente nella finestra di login | /Library/Preferences/com.apple.loginwindow.plist | lastUserName |
| Login automatico | /Library/Preferences/com.apple.loginwindow.plist | autoLoginUser (password offuscata in /private/etc/kcpassword) |
| Reti Wi-Fi note | /Library/Preferences/com.apple.wifi.known-networks.plist | Una voce per rete, wifi.network.ssid.<SSID>, con AddedAt, JoinedByUserAt, JoinedBySystemAt |
| Dispositivi Bluetooth | /Library/Preferences/com.apple.Bluetooth.plist | Indirizzi e nomi dei dispositivi abbinati |
| Account locali | /private/var/db/dslocal/nodes/Default/users/<name>.plist | uid, home, generateduid, accountPolicyData |
| Amministratori | /private/var/db/dslocal/nodes/Default/groups/admin.plist | users, groupmembers |
| Installazioni e aggiornamenti | /Library/Receipts/InstallHistory.plist | date, displayName, displayVersion, processName |
SystemVersion.plist si trova sul volume System e può mancare in una raccolta del volume Data; in tal caso, InstallHistory.plist fornisce le versioni installate. Il file Wi-Fi ha sostituito il dizionario KnownNetworks di /Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist durante il ciclo di macOS 11 Big Sur; sui sistemi meno recenti, leggere invece quel file. Il fuso orario è indicato dalla destinazione del collegamento, non dal contenuto del file di zona.
Account
macOS conserva gli account locali nel nodo locale del servizio di directory, con un plist binario per account in /private/var/db/dslocal/nodes/Default/users/, leggibile solo da root su un sistema in esecuzione. Ogni attributo è un array, anche quando contiene un solo valore: uid è ["501"], sotto forma di stringa. Le chiavi utili sono name (nome breve), realname (nome completo), uid, gid (20, staff, per gli utenti normali), home, shell, generateduid (un UUID che identifica l'account nell'appartenenza ai gruppi), authentication_authority e:
accountPolicyData: un plist annidato concreationTime,passwordLastSetTime,failedLoginCountefailedLoginTimestamp. Questi tempi sono secondi Unix memorizzati come reali, non Mac Absolute Time. Il contatore degli errori si azzera dopo l'inserimento di una password corretta. Per la cronologia degli accessi, utilizzare i log unificati (lezione 6.2).ShadowHashData: un plist annidato con l'hash della password,SALTED-SHA512-PBKDF2(entropy,salt,iterations) a partire da OS X 10.8. Dimostra che un account dispone di una password locale; il recupero delle password esula da questo corso.
Il primo account creato in Impostazione Assistita riceve l'UID 501, il successivo 502. Gli account i cui nomi iniziano con _ sono account di servizio del sistema con UID bassi. In groups/admin.plist (GID 80), users elenca i nomi brevi e groupmembers elenca i valori generateduid; verificare entrambi. Su un Mac in esecuzione, dscl . -list /Users UniqueID e dscl . -read /Users/<name> mostrano gli stessi dati. Un account mobile è una copia memorizzata nella cache locale di un account di directory (ad esempio Active Directory); il suo authentication_authority contiene LocalCachedUser e il suo UID proviene generalmente dalla directory ed è molto superiore a 501.
Data di installazione e aggiornamenti
/private/var/db/.AppleSetupDone è un file vuoto creato al termine di Impostazione Assistita, quindi i suoi timestamp indicano quando il sistema è stato configurato; configurazioni successive agli aggiornamenti del sistema operativo possono riscriverlo, quindi occorre verificarlo mediante riscontro con il creationTime del primo utente e le voci più antiche di InstallHistory.plist. Ogni voce di InstallHistory.plist registra un'installazione: aggiornamenti di macOS (processName come softwareupdated), app dell'App Store e pacchetti di installazione. /private/var/db/receipts e /private/var/log/install.log forniscono riscontri.
Acquisizione da un Mac moderno
Sui Mac con T2 e Apple silicon, un'immagine fisica separata dall'hardware originale è illeggibile (lezione 1.7) e un'immagine completa del sistema in esecuzione e sbloccato è spesso poco praticabile. Gli esaminatori eseguono quindi una raccolta logica di triage dal Mac in esecuzione e sbloccato: sudo log collect --output <dest>.logarchive per i log unificati, più copie dei file di /Users, /Library e /private/var effettuate con uno strumento a cui sia stato concesso Accesso completo al disco in Privacy e Sicurezza. In sua assenza, le protezioni della privacy (TCC) bloccano senza avvisi Mail, Messaggi, Safari e altri dati protetti. Documentare ciò che non è stato possibile leggere e calcolare l'hash dell'output. Esempi gratuiti: Aftermath (raccolta e analisi open source), mac_apt (analizza immagini e cartelle raccolte), APOLLO (database dei modelli di attività quotidiana, lezione 6.2) e plutil.
Esempio svolto: decodifica di valori plist e di una stringa di quarantena
loginwindow. In un com.apple.loginwindow.plist binario compaiono gli oggetti 5C 6C 61 73 74 55 73 65 72 4E 61 6D 65 e 54 61 6C 65 78. Il marcatore 0x5C indica una stringa ASCII di 12 caratteri: lastUserName. Il marcatore 0x54 indica una stringa ASCII di 4 caratteri: alex. Il dizionario li associa, quindi lastUserName = alex.
Data di InstallHistory. Una voce con displayName "macOS Sequoia 15.1" contiene un oggetto date pari a 33 41 C6 6C 84 94 80 00 00. Il marcatore 0x33 indica una data; gli otto byte successivi sono un double big-endian:
python3 -c "import struct; print(struct.unpack('>d', bytes.fromhex('41c66c8494800000')))"visualizza752421161.0.- Tempo Unix = 752.421.161 + 978.307.200 = 1.730.728.361.
python3 -c "import datetime as d; print(d.datetime.fromtimestamp(1730728361, d.timezone.utc))"visualizza2024-11-04 13:52:41+00:00, quindi 2024-11-04T13:52:41Z.
Quarantena. xattr -l su ~/Downloads/tool.dmg mostra com.apple.quarantine: 0083;65f2c1a3;Safari; seguito da un UUID.
- 0x65F2C1A3 = 6×16^7 + 5×16^6 + 15×16^5 + 2×16^4 + 12×16^3 + 1×16^2 + 10×16 + 3 = 1.710.408.099.
python3 -c "import datetime as d; print(d.datetime.fromtimestamp(0x65f2c1a3, d.timezone.utc))"visualizza2024-03-14 09:21:39+00:00, quindi Safari ha messo il file in quarantena alle 2024-03-14T09:21:39Z.
Verificare mediante riscontro con la riga contenente l'UUID corrispondente in QuarantineEventsV2, i cui tempi sono espressi in Mac Absolute Time, e con l'ora di creazione APFS del file. L'ora di quarantena è impostata dall'app che effettua il download e non dimostra che il file sia mai stato aperto.
Focus sull'esame: Occorre saper associare una domanda alla relativa fonte: versione inSystemVersion.plist, nomi inpreferences.plist, ultimo utente incom.apple.loginwindow.plist, account e appartenenza al gruppo degli amministratori indslocal, installazioni inInstallHistory.plist. Prepararsi a identificare un plist binario tramitebplist00, decodificare una data plist come Mac Absolute Time, convertire il tempo Unix esadecimale in una stringa di quarantena e spiegare perché gli attributi estesi scompaiono quando i file vengono copiati su file system privi di supporto xattr.
Punti chiave
- Gli elementi di prova relativi agli utenti si trovano in
/Users/<name>/Library(Preferences, Application Support, Containers, Group Containers) e in/private/var(db,log,folders); le app in sandbox conservano i propri dati nel rispettivo contenitore. com.apple.quarantinecontiene flag, un timestamp Unix esadecimale, l'agente che effettua il download e un UUID;kMDItemWhereFromscontiene gli URL di origine. Entrambi si conservano solo dove gli xattr sono supportati o trasportati nei file AppleDouble._.- I plist esistono in formato XML e binario (
bplist00); le date binarie sono double big-endian espressi in Mac Absolute Time; i plist annidati e gli archivi NSKeyedArchiver richiedono un secondo passaggio di decodifica.plutil -convertsenza-osovrascrive il file. - Gli account locali sono plist per utente in
dslocal: il primo utente ha UID 501, l'appartenenza al gruppo degli amministratori si trova ingroups/admin.pliste i tempi diaccountPolicyDatasono espressi in secondi Unix. - Sui Mac moderni si esegue generalmente un'acquisizione logica dal sistema in esecuzione e sbloccato, con Accesso completo al disco e
log collect.