macOS MACF - Mandatory Access Control Framework
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
MACF sta per Mandatory Access Control Framework, che è un sistema di sicurezza integrato nel sistema operativo per aiutare a proteggere il computer. Funziona impostando regole rigorose su chi o cosa può accedere a determinate parti del sistema, come file, applicazioni e risorse di sistema. Applicando automaticamente queste regole, MACF garantisce che solo utenti e processi autorizzati possano eseguire azioni specifiche, riducendo il rischio di accesso non autorizzato o attività dannose.
Nota che MACF non prende realmente decisioni poiché intercetta solo le azioni, lasciando le decisioni ai moduli di policy (estensioni del kernel) che chiama come AppleMobileFileIntegrity.kext
, Quarantine.kext
, Sandbox.kext
, TMSafetyNet.kext
e mcxalr.kext
.
Il processo esegue una syscall/mach trap
La funzione pertinente viene chiamata all'interno del kernel
La funzione chiama MACF
MACF controlla i moduli di policy che hanno richiesto di agganciarsi a quella funzione nella loro policy
MACF chiama le policy pertinenti
Le policy indicano se consentono o negano l'azione
Apple è l'unica che può utilizzare il KPI del MAC Framework.
MACF utilizza etichette che poi le policy controllano per decidere se concedere o meno l'accesso. Il codice della dichiarazione della struttura delle etichette può essere trovato qui, che viene poi utilizzato all'interno della struct ucred
in qui nella parte cr_label
. L'etichetta contiene flag e un numero di slot che possono essere utilizzati dalle policy MACF per allocare puntatori. Ad esempio, Sanbox punterà al profilo del contenitore.
Una policy MACF definisce regole e condizioni da applicare in determinate operazioni del kernel.
Un'estensione del kernel potrebbe configurare una struttura mac_policy_conf
e poi registrarla chiamando mac_policy_register
. Da qui:
È facile identificare le estensioni del kernel che configurano queste politiche controllando le chiamate a mac_policy_register
. Inoltre, controllando il disassemblaggio dell'estensione è anche possibile trovare la struct mac_policy_conf
utilizzata.
Nota che le politiche MACF possono essere registrate e deregistrate anche dinamicamente.
Uno dei principali campi della mac_policy_conf
è mpc_ops
. Questo campo specifica quali operazioni interessano la politica. Nota che ce ne sono centinaia, quindi è possibile azzerarle tutte e poi selezionare solo quelle di interesse per la politica. Da qui:
Quasi tutti i hook verranno richiamati da MACF quando una di queste operazioni viene intercettata. Tuttavia, i hook mpo_policy_*
sono un'eccezione perché mpo_hook_policy_init()
è un callback chiamato al momento della registrazione (quindi dopo mac_policy_register()
) e mpo_hook_policy_initbsd()
viene chiamato durante la registrazione tardiva una volta che il sottosistema BSD è stato inizializzato correttamente.
Inoltre, il hook mpo_policy_syscall
può essere registrato da qualsiasi kext per esporre un'interfaccia di chiamata in stile ioctl privata. Quindi, un client utente sarà in grado di chiamare mac_syscall
(#381) specificando come parametri il nome della policy con un codice intero e argomenti opzionali.
Ad esempio, il Sandbox.kext
utilizza molto questo.
Controllando il __DATA.__const*
del kext è possibile identificare la struttura mac_policy_ops
utilizzata durante la registrazione della policy. È possibile trovarla perché il suo puntatore si trova a un offset all'interno di mpo_policy_conf
e anche a causa della quantità di puntatori NULL che saranno in quell'area.
Inoltre, è anche possibile ottenere l'elenco dei kext che hanno configurato una policy eseguendo il dump dalla memoria della struttura _mac_policy_list
che viene aggiornata con ogni policy registrata.
MACF viene inizializzato molto presto. Viene impostato nel bootstrap_thread
di XNU: dopo ipc_bootstrap
viene effettuata una chiamata a mac_policy_init()
che inizializza la mac_policy_list
e momenti dopo viene chiamato mac_policy_initmach()
. Tra le altre cose, questa funzione otterrà tutti i kext Apple con la chiave AppleSecurityExtension
nel loro Info.plist come ALF.kext
, AppleMobileFileIntegrity.kext
, Quarantine.kext
, Sandbox.kext
e TMSafetyNet.kext
e li carica.
È comune trovare chiamate a MACF definite nel codice come: #if CONFIG_MAC
blocchi condizionali. Inoltre, all'interno di questi blocchi è possibile trovare chiamate a mac_proc_check*
che chiamano MACF per controllare i permessi per eseguire determinate azioni. Inoltre, il formato delle chiamate a MACF è: mac_<object>_<opType>_opName
.
L'oggetto è uno dei seguenti: bpfdesc
, cred
, file
, proc
, vnode
, mount
, devfs
, ifnet
, inpcb
, mbuf
, ipq
, pipe
, sysv[msg/msq/shm/sem]
, posix[shm/sem]
, socket
, kext
.
L'opType
è solitamente check che verrà utilizzato per consentire o negare l'azione. Tuttavia, è anche possibile trovare notify
, che consentirà al kext di reagire all'azione data.
Puoi trovare un esempio in https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/kern/kern_mman.c#L621:
Poi, è possibile trovare il codice di mac_file_check_mmap
in https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/security/mac_file.c#L174
Quale sta chiamando il macro MAC_CHECK
, il cui codice può essere trovato in https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/security/mac_internal.h#L261
Quale passerà in rassegna tutte le politiche mac registrate chiamando le loro funzioni e memorizzando l'output all'interno della variabile error, che sarà sovrascrivibile solo da mac_error_select
tramite codici di successo, quindi se un controllo fallisce, il controllo completo fallirà e l'azione non sarà consentita.
Tuttavia, ricorda che non tutte le chiamate MACF vengono utilizzate solo per negare azioni. Ad esempio, mac_priv_grant
chiama il macro MAC_GRANT, che concederà il privilegio richiesto se qualche politica risponde con un 0:
Queste chiamate sono destinate a controllare e fornire (decine di) privilegi definiti in bsd/sys/priv.h.
Alcuni codici del kernel chiamerebbero priv_check_cred()
da bsd/kern/kern_priv.c con le credenziali KAuth del processo e uno dei codici di privilegio che chiamerà mac_priv_check
per vedere se qualche politica nega il conferimento del privilegio e poi chiama mac_priv_grant
per vedere se qualche politica concede il privilegio
.
Questo hook consente di intercettare tutte le chiamate di sistema. In bsd/dev/[i386|arm]/systemcalls.c
è possibile vedere la funzione dichiarata unix_syscall
, che contiene questo codice:
Quale controllerà nel processo chiamante bitmask se la syscall corrente dovrebbe chiamare mac_proc_check_syscall_unix
. Questo perché le syscall vengono chiamate così frequentemente che è interessante evitare di chiamare mac_proc_check_syscall_unix
ogni volta.
Nota che la funzione proc_set_syscall_filter_mask()
, che imposta il bitmask delle syscall in un processo, è chiamata da Sandbox per impostare le maschere sui processi sandboxed.
È possibile interagire con MACF attraverso alcune syscall definite in security/mac.h:
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)