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 označava Okvir obaveznog pristupa, koji je bezbednosni sistem ugrađen u operativni sistem kako bi pomogao u zaštiti vašeg računara. Funkcioniše tako što postavlja stroga pravila o tome ko ili šta može pristupiti određenim delovima sistema, kao što su datoteke, aplikacije i sistemski resursi. Sprovodeći ova pravila automatski, MACF osigurava da samo ovlašćeni korisnici i procesi mogu izvršavati određene radnje, smanjujući rizik od neovlašćenog pristupa ili zlonamernih aktivnosti.
Napomena: MACF zapravo ne donosi nikakve odluke, već samo presreće radnje, ostavljajući odluke modulima politike (kernel ekstenzije) koje poziva, kao što su AppleMobileFileIntegrity.kext
, Quarantine.kext
, Sandbox.kext
, TMSafetyNet.kext
i mcxalr.kext
.
Proces izvršava syscall/mach trap
Relevantna funkcija se poziva unutar kernela
Funkcija poziva MACF
MACF proverava module politike koji su zatražili da se ta funkcija poveže u svojoj politici
MACF poziva relevantne politike
Politike označavaju da li dozvoljavaju ili odbacuju radnju
Apple je jedini koji može koristiti MAC Framework KPI.
MACF koristi oznake koje zatim politike koriste da provere da li treba da odobre neki pristup ili ne. Kod deklaracije strukture oznaka može se pronaći ovde, koja se zatim koristi unutar struct ucred
ovde u delu cr_label
. Oznaka sadrži zastavice i broj slotova koji se mogu koristiti od strane MACF politika za dodelu pokazivača. Na primer, Sandbox će ukazivati na profil kontejnera.
MACF politika definiše pravila i uslove koji se primenjuju u određenim operacijama kernela.
Kernel ekstenzija može konfigurisati mac_policy_conf
strukturu i zatim je registrovati pozivajući mac_policy_register
. Od ovde:
Lako je identifikovati kernel ekstenzije koje konfigurišu ove politike proverom poziva na mac_policy_register
. Štaviše, proverom disasembla ekstenzije takođe je moguće pronaći korišćenu mac_policy_conf
strukturu.
Napomena da se MACF politike mogu registrovati i deregistrovati takođe dinamički.
Jedno od glavnih polja mac_policy_conf
je mpc_ops
. Ovo polje specificira koje operacije politika zanima. Napomena da ih ima stotine, tako da je moguće postaviti sve na nulu, a zatim izabrati samo one koje politiku zanimaju. Od ovde:
Almost all the hooks will be called back by MACF when one of those operations are intercepted. However, mpo_policy_*
hooks are an exception because mpo_hook_policy_init()
is a callback called upon registration (so after mac_policy_register()
) and mpo_hook_policy_initbsd()
is called during late registration once the BSD subsystem has initialised properly.
Moreover, the mpo_policy_syscall
hook can be registered by any kext to expose a private ioctl style call interface. Then, a user client will be able to call mac_syscall
(#381) specifying as parameters the policy name with an integer code and optional arguments.
For example, the Sandbox.kext
uses this a lot.
Checking the kext's __DATA.__const*
is possible to identify the mac_policy_ops
structure used when registering the policy. It's possible to find it because its pointer is at an offset inside mpo_policy_conf
and also because the amount of NULL pointers that will be in that area.
Moreover, it's also possible to get the list of kexts that have configured a policy by dumping from memory the struct _mac_policy_list
which is updated with every policy that is registered.
MACF is initialised very soon. It's set up in XNU's bootstrap_thread
: after ipc_bootstrap
a call to mac_policy_init()
which initializes the mac_policy_list
and moments later mac_policy_initmach()
is called. Among other things, this function will get all the Apple kexts with the AppleSecurityExtension
key in their Info.plist like ALF.kext
, AppleMobileFileIntegrity.kext
, Quarantine.kext
, Sandbox.kext
and TMSafetyNet.kext
and loads them.
It's common to find callouts to MACF defined in code like: #if CONFIG_MAC
conditional blocks. Moreover, inside these blocks it's possible to find calls to mac_proc_check*
which calls MACF to check for permissions to perform certain actions. Moreover, the format of the MACF callouts is: mac_<object>_<opType>_opName
.
The object is one of the following: bpfdesc
, cred
, file
, proc
, vnode
, mount
, devfs
, ifnet
, inpcb
, mbuf
, ipq
, pipe
, sysv[msg/msq/shm/sem]
, posix[shm/sem]
, socket
, kext
.
The opType
is usually check which will be used to allow or deny the action. However, it's also possible to find notify
, which will allow the kext to react to the given action.
You can find an example in https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/kern/kern_mman.c#L621:
Then, it's possible to find the code of mac_file_check_mmap
in https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/security/mac_file.c#L174
Koji poziva MAC_CHECK
makro, čiji se kod može naći na https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/security/mac_internal.h#L261
Koji će proći kroz sve registrovane mac politike pozivajući njihove funkcije i čuvajući izlaz unutar promenljive error, koja će biti prepisiva samo od strane mac_error_select
pomoću kodova uspeha, tako da ako bilo koja provera ne uspe, cela provera će pasti i akcija neće biti dozvoljena.
Međutim, zapamtite da se ne koriste svi MACF pozivi samo za odbijanje akcija. Na primer, mac_priv_grant
poziva makro MAC_GRANT, koji će odobriti traženu privilegiju ako bilo koja politika odgovori sa 0:
Ove funkcije su namenjene za proveru i dodeljivanje (desetina) privilegija definisanih u bsd/sys/priv.h.
Neki kernel kod bi pozvao priv_check_cred()
iz bsd/kern/kern_priv.c sa KAuth kredencijalima procesa i jednim od kodova privilegija koji će pozvati mac_priv_check
da vidi da li neka politika odbija dodeljivanje privilegije, a zatim poziva mac_priv_grant
da vidi da li neka politika dodeljuje privilegiju
.
Ova tačka omogućava presretanje svih sistemskih poziva. U bsd/dev/[i386|arm]/systemcalls.c
moguće je videti deklarisanu funkciju unix_syscall
, koja sadrži ovaj kod:
Koji će proveriti u pozivnom procesu bitmasku da li trenutni syscall treba da pozove mac_proc_check_syscall_unix
. To je zato što se syscalls pozivaju tako često da je zanimljivo izbeći pozivanje mac_proc_check_syscall_unix
svaki put.
Napomena da funkcija proc_set_syscall_filter_mask()
, koja postavlja bitmasku syscalls u procesu, se poziva od strane Sandbox-a da postavi maske na sandboxed procesima.
Moguće je interagovati sa MACF kroz neke syscalls definisane u security/mac.h:
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)