# macOS MACF {% hint style="success" %} Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Support HackTricks * Check the [**subscription plans**](https://github.com/sponsors/carlospolop)! * **Join the** 馃挰 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 馃惁 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** * **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
{% endhint %} ## Podstawowe informacje **MACF** oznacza **Mandatory Access Control Framework**, kt贸ry jest systemem zabezpiecze艅 wbudowanym w system operacyjny, aby pom贸c chroni膰 komputer. Dzia艂a poprzez ustalanie **艣cis艂ych zasad dotycz膮cych tego, kto lub co mo偶e uzyska膰 dost臋p do okre艣lonych cz臋艣ci systemu**, takich jak pliki, aplikacje i zasoby systemowe. Dzi臋ki automatycznemu egzekwowaniu tych zasad, MACF zapewnia, 偶e tylko autoryzowani u偶ytkownicy i procesy mog膮 wykonywa膰 okre艣lone dzia艂ania, co zmniejsza ryzyko nieautoryzowanego dost臋pu lub z艂o艣liwych dzia艂a艅. Nale偶y zauwa偶y膰, 偶e MACF nie podejmuje 偶adnych decyzji, poniewa偶 po prostu **przechwytuje** dzia艂ania, pozostawiaj膮c decyzje modu艂om **polityki** (rozszerzenia j膮dra), kt贸re wywo艂uje, takim jak `AppleMobileFileIntegrity.kext`, `Quarantine.kext`, `Sandbox.kext`, `TMSafetyNet.kext` i `mcxalr.kext`. ### Przep艂yw 1. Proces wykonuje syscall/mach trap 2. Odpowiednia funkcja jest wywo艂ywana wewn膮trz j膮dra 3. Funkcja wywo艂uje MACF 4. MACF sprawdza modu艂y polityki, kt贸re za偶膮da艂y podpi臋cia tej funkcji w swojej polityce 5. MACF wywo艂uje odpowiednie polityki 6. Polityki wskazuj膮, czy zezwalaj膮 na dzia艂anie, czy je odrzucaj膮 {% hint style="danger" %} Apple jest jedyn膮 firm膮, kt贸ra mo偶e korzysta膰 z KPI Framework MAC. {% endhint %} ### Etykiety MACF u偶ywa **etykiet**, kt贸re nast臋pnie polityki sprawdzaj膮, czy powinny przyzna膰 dost臋p, czy nie. Kod deklaracji struktury etykiet mo偶na [znale藕膰 tutaj](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/security/_label.h), kt贸ra jest nast臋pnie u偶ywana wewn膮trz **`struct ucred`** w [**tutaj**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/sys/ucred.h#L86) w cz臋艣ci **`cr_label`**. Etykieta zawiera flagi i liczb臋 **slot贸w**, kt贸re mog膮 by膰 u偶ywane przez **polityki MACF do alokacji wska藕nik贸w**. Na przyk艂ad Sanbox b臋dzie wskazywa艂 na profil kontenera. ## Polityki MACF Polityka MACF definiuje **zasady i warunki, kt贸re maj膮 by膰 stosowane w okre艣lonych operacjach j膮dra**. Rozszerzenie j膮dra mo偶e skonfigurowa膰 struktur臋 `mac_policy_conf`, a nast臋pnie zarejestrowa膰 j膮, wywo艂uj膮c `mac_policy_register`. Z [tutaj](https://opensource.apple.com/source/xnu/xnu-2050.18.24/security/mac_policy.h.auto.html): ```c #define mpc_t struct mac_policy_conf * /** @brief Mac policy configuration This structure specifies the configuration information for a MAC policy module. A policy module developer must supply a short unique policy name, a more descriptive full name, a list of label namespaces and count, a pointer to the registered enty point operations, any load time flags, and optionally, a pointer to a label slot identifier. The Framework will update the runtime flags (mpc_runtime_flags) to indicate that the module has been registered. If the label slot identifier (mpc_field_off) is NULL, the Framework will not provide label storage for the policy. Otherwise, the Framework will store the label location (slot) in this field. The mpc_list field is used by the Framework and should not be modified by policies. */ /* XXX - reorder these for better aligment on 64bit platforms */ struct mac_policy_conf { const char *mpc_name; /** policy name */ const char *mpc_fullname; /** full name */ const char **mpc_labelnames; /** managed label namespaces */ unsigned int mpc_labelname_count; /** number of managed label namespaces */ struct mac_policy_ops *mpc_ops; /** operation vector */ int mpc_loadtime_flags; /** load time flags */ int *mpc_field_off; /** label slot */ int mpc_runtime_flags; /** run time flags */ mpc_t mpc_list; /** List reference */ void *mpc_data; /** module data */ }; ``` 艁atwo jest zidentyfikowa膰 rozszerzenia j膮dra konfigurowane przez te polityki, sprawdzaj膮c wywo艂ania do `mac_policy_register`. Co wi臋cej, sprawdzaj膮c dezasemblacj臋 rozszerzenia, mo偶na r贸wnie偶 znale藕膰 u偶ywan膮 struktur臋 `mac_policy_conf`. Zauwa偶, 偶e polityki MACF mog膮 by膰 rejestrowane i deregisterowane r贸wnie偶 **dynamicznie**. Jednym z g艂贸wnych p贸l `mac_policy_conf` jest **`mpc_ops`**. To pole okre艣la, kt贸rymi operacjami polityka jest zainteresowana. Zauwa偶, 偶e jest ich setki, wi臋c mo偶liwe jest wyzerowanie wszystkich z nich, a nast臋pnie wybranie tylko tych, kt贸rymi polityka jest zainteresowana. Z [tutaj](https://opensource.apple.com/source/xnu/xnu-2050.18.24/security/mac\_policy.h.auto.html): ```c struct mac_policy_ops { mpo_audit_check_postselect_t *mpo_audit_check_postselect; mpo_audit_check_preselect_t *mpo_audit_check_preselect; mpo_bpfdesc_label_associate_t *mpo_bpfdesc_label_associate; mpo_bpfdesc_label_destroy_t *mpo_bpfdesc_label_destroy; mpo_bpfdesc_label_init_t *mpo_bpfdesc_label_init; mpo_bpfdesc_check_receive_t *mpo_bpfdesc_check_receive; mpo_cred_check_label_update_execve_t *mpo_cred_check_label_update_execve; mpo_cred_check_label_update_t *mpo_cred_check_label_update; [...] ``` 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 Initialization 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. ## MACF Callouts 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___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](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/kern/kern\_mman.c#L621):
int
mmap(proc_t p, struct mmap_args *uap, user_addr_t *retval)
{
[...]
#if CONFIG_MACF
			error = mac_file_check_mmap(vfs_context_ucred(ctx),
			    fp->fp_glob, prot, flags, file_pos + pageoff,
&maxprot);
if (error) {
(void)vnode_put(vp);
goto bad;
}
#endif /* MAC */
[...]
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](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/security/mac\_file.c#L174) ```c mac_file_check_mmap(struct ucred *cred, struct fileglob *fg, int prot, int flags, uint64_t offset, int *maxprot) { int error; int maxp; maxp = *maxprot; MAC_CHECK(file_check_mmap, cred, fg, NULL, prot, flags, offset, &maxp); if ((maxp | *maxprot) != *maxprot) { panic("file_check_mmap increased max protections"); } *maxprot = maxp; return error; } ``` Kt贸ry wywo艂uje makro `MAC_CHECK`, kt贸rego kod mo偶na znale藕膰 w [https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/security/mac\_internal.h#L261](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/security/mac\_internal.h#L261) ```c /* * MAC_CHECK performs the designated check by walking the policy * module list and checking with each as to how it feels about the * request. Note that it returns its value via 'error' in the scope * of the caller. */ #define MAC_CHECK(check, args...) do { \ error = 0; \ MAC_POLICY_ITERATE({ \ if (mpc->mpc_ops->mpo_ ## check != NULL) { \ DTRACE_MACF3(mac__call__ ## check, void *, mpc, int, error, int, MAC_ITERATE_CHECK); \ int __step_err = mpc->mpc_ops->mpo_ ## check (args); \ DTRACE_MACF2(mac__rslt__ ## check, void *, mpc, int, __step_err); \ error = mac_error_select(__step_err, error); \ } \ }); \ } while (0) ``` Kt贸re przejdzie przez wszystkie zarejestrowane polityki mac, wywo艂uj膮c ich funkcje i przechowuj膮c wynik w zmiennej error, kt贸ra b臋dzie mog艂a by膰 nadpisywana tylko przez `mac_error_select` za pomoc膮 kod贸w sukcesu, wi臋c je艣li jakiekolwiek sprawdzenie si臋 nie powiedzie, ca艂e sprawdzenie si臋 nie powiedzie, a akcja nie b臋dzie dozwolona. {% hint style="success" %} Jednak pami臋taj, 偶e nie wszystkie wywo艂ania MACF s膮 u偶ywane tylko do odrzucania akcji. Na przyk艂ad, `mac_priv_grant` wywo艂uje makro [**MAC\_GRANT**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/security/mac\_internal.h#L274), kt贸re przyzna 偶膮dane uprawnienie, je艣li jakakolwiek polityka odpowie 0: ```c /* * MAC_GRANT performs the designated check by walking the policy * module list and checking with each as to how it feels about the * request. Unlike MAC_CHECK, it grants if any policies return '0', * and otherwise returns EPERM. Note that it returns its value via * 'error' in the scope of the caller. */ #define MAC_GRANT(check, args...) do { \ error = EPERM; \ MAC_POLICY_ITERATE({ \ if (mpc->mpc_ops->mpo_ ## check != NULL) { \ DTRACE_MACF3(mac__call__ ## check, void *, mpc, int, error, int, MAC_ITERATE_GRANT); \ int __step_res = mpc->mpc_ops->mpo_ ## check (args); \ if (__step_res == 0) { \ error = 0; \ } \ DTRACE_MACF2(mac__rslt__ ## check, void *, mpc, int, __step_res); \ } \ }); \ } while (0) ``` {% endhint %} ### priv\_check & priv\_grant Te wywo艂ania maj膮 na celu sprawdzenie i przyznanie (dziesi膮tek) **uprawnie艅** zdefiniowanych w [**bsd/sys/priv.h**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/sys/priv.h).\ Niekt贸re kody j膮dra wywo艂aj膮 `priv_check_cred()` z [**bsd/kern/kern\_priv.c**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/kern/kern_priv.c) z po艣wiadczeniami KAuth procesu oraz jednym z kod贸w uprawnie艅, kt贸re wywo艂aj膮 `mac_priv_check`, aby sprawdzi膰, czy jakakolwiek polityka **odmawia** przyznania uprawnienia, a nast臋pnie wywo艂uje `mac_priv_grant`, aby sprawdzi膰, czy jakakolwiek polityka przyznaje `uprawnienie`. ### proc\_check\_syscall\_unix Ten hak pozwala na przechwytywanie wszystkich wywo艂a艅 systemowych. W `bsd/dev/[i386|arm]/systemcalls.c` mo偶na zobaczy膰 zadeklarowan膮 funkcj臋 [`unix_syscall`](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/dev/arm/systemcalls.c#L160C1-L167C25), kt贸ra zawiera ten kod: ```c #if CONFIG_MACF if (__improbable(proc_syscall_filter_mask(proc) != NULL && !bitstr_test(proc_syscall_filter_mask(proc), syscode))) { error = mac_proc_check_syscall_unix(proc, syscode); if (error) { goto skip_syscall; } } #endif /* CONFIG_MACF */ ``` Kt贸ry sprawdzi w wywo艂uj膮cym procesie **bitmask**, czy bie偶膮cy syscall powinien wywo艂a膰 `mac_proc_check_syscall_unix`. Dzieje si臋 tak, poniewa偶 syscalls s膮 wywo艂ywane tak cz臋sto, 偶e warto unika膰 wywo艂ywania `mac_proc_check_syscall_unix` za ka偶dym razem. Zauwa偶, 偶e funkcja `proc_set_syscall_filter_mask()`, kt贸ra ustawia bitmask syscalls w procesie, jest wywo艂ywana przez Sandbox w celu ustawienia masek na procesach w piaskownicy. ## Ekspozycja syscalli MACF Mo偶liwe jest interakcja z MACF za pomoc膮 niekt贸rych syscalli zdefiniowanych w [security/mac.h](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/security/mac.h#L151): ```c /* * Extended non-POSIX.1e interfaces that offer additional services * available from the userland and kernel MAC frameworks. */ #ifdef __APPLE_API_PRIVATE __BEGIN_DECLS int __mac_execve(char *fname, char **argv, char **envv, mac_t _label); int __mac_get_fd(int _fd, mac_t _label); int __mac_get_file(const char *_path, mac_t _label); int __mac_get_link(const char *_path, mac_t _label); int __mac_get_pid(pid_t _pid, mac_t _label); int __mac_get_proc(mac_t _label); int __mac_set_fd(int _fildes, const mac_t _label); int __mac_set_file(const char *_path, mac_t _label); int __mac_set_link(const char *_path, mac_t _label); int __mac_mount(const char *type, const char *path, int flags, void *data, struct mac *label); int __mac_get_mount(const char *path, struct mac *label); int __mac_set_proc(const mac_t _label); int __mac_syscall(const char *_policyname, int _call, void *_arg); __END_DECLS #endif /*__APPLE_API_PRIVATE*/ ``` ## References * [**\*OS Internals Volume III**](https://newosxbook.com/home.html) {% hint style="success" %} Ucz si臋 i 膰wicz Hacking AWS:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ Ucz si臋 i 膰wicz Hacking GCP: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Wsparcie dla HackTricks * Sprawd藕 [**plany subskrypcyjne**](https://github.com/sponsors/carlospolop)! * **Do艂膮cz do** 馃挰 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **艣led藕** nas na **Twitterze** 馃惁 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** * **Dziel si臋 trikami hackingowymi, przesy艂aj膮c PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repozytori贸w na githubie.
{% endhint %}