macOS MACF
Reading time: 11 minutes
tip
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Basiese Inligting
MACF staan vir Verpligte Toegang Beheer Raamwerk, wat 'n sekuriteitstelsel is wat in die bedryfstelsel ingebou is om jou rekenaar te help beskerm. Dit werk deur strenge reëls op te stel oor wie of wat toegang tot sekere dele van die stelsel kan hê, soos lêers, toepassings en stelselhulpbronne. Deur hierdie reëls outomaties af te dwing, verseker MACF dat slegs gemagtigde gebruikers en prosesse spesifieke aksies kan uitvoer, wat die risiko van ongemagtigde toegang of kwaadwillige aktiwiteite verminder.
Let daarop dat MACF nie werklik enige besluite neem nie, aangesien dit net aksies onderskep, dit laat die besluite aan die beleidsmodules (kernel uitbreidings) wat dit aanroep soos AppleMobileFileIntegrity.kext
, Quarantine.kext
, Sandbox.kext
, TMSafetyNet.kext
en mcxalr.kext
.
Stroom
- Proses voer 'n syscall/mach trap uit
- Die relevante funksie word binne die kernel aangeroep
- Funksie roep MACF aan
- MACF kontroleer beleidsmodules wat versoek het om daardie funksie in hul beleid te haak
- MACF roep die relevante beleids aan
- Beleide dui aan of hulle die aksie toelaat of weier
caution
Apple is die enigste wat die MAC Framework KPI kan gebruik.
Etikette
MACF gebruik etikette wat dan deur die beleide nagegaan word of hulle sekere toegang moet toestaan of nie. Die kode van die etikette struktuurdeklarasie kan hier gevind word, wat dan binne die struct ucred
in hier in die cr_label
deel gebruik word. Die etiket bevat vlae en 'n aantal slots wat deur MACF beleide gebruik kan word om wysers toe te ken. Byvoorbeeld, Sanbox sal na die houerprofiel wys.
MACF Beleide
'n MACF Beleid definieer reëls en voorwaardes wat in sekere kernel operasies toegepas moet word.
'n Kernel uitbreiding kan 'n mac_policy_conf
struktuur konfigureer en dit dan registreer deur mac_policy_register
aan te roep. Van hier:
#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 */
};
Dit is maklik om die kernuitbreidings wat hierdie beleide konfigureer te identifiseer deur oproepe na mac_policy_register
te kontroleer. Boonop, deur die disassemble van die uitbreiding te kontroleer, is dit ook moontlik om die gebruikte mac_policy_conf
struktuur te vind.
Let daarop dat MACF beleide ook dynamies geregistreer en ongeregistreer kan word.
Een van die hoofvelde van die mac_policy_conf
is die mpc_ops
. Hierdie veld spesifiseer watter operasies die beleid belangrik vind. Let daarop dat daar honderde daarvan is, so dit is moontlik om al hulle op nul te stel en dan net diegene te kies waarin die beleid belangstel. Van hier:
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;
[...]
Byna al die hooks sal deur MACF teruggeroep word wanneer een van daardie operasies geïntercepteer word. egter, mpo_policy_*
hooks is 'n uitsondering omdat mpo_hook_policy_init()
'n terugroep is wat tydens registrasie aangeroep word (so na mac_policy_register()
) en mpo_hook_policy_initbsd()
word tydens laat registrasie aangeroep sodra die BSD subsisteem behoorlik geinitialiseer is.
Boonop kan die mpo_policy_syscall
hook deur enige kext geregistreer word om 'n private ioctl styl oproep interface bloot te stel. Dan sal 'n gebruikersklient in staat wees om mac_syscall
(#381) aan te roep en die beleidsnaam met 'n heelgetal kode en opsionele argumente as parameters te spesifiseer.
Byvoorbeeld, die Sandbox.kext
gebruik dit baie.
Deur die kext se __DATA.__const*
te kontroleer, is dit moontlik om die mac_policy_ops
struktuur te identifiseer wat gebruik word wanneer die beleid geregistreer word. Dit is moontlik om dit te vind omdat sy pointer op 'n offset binne mpo_policy_conf
is en ook omdat die hoeveelheid NULL pointers wat in daardie area sal wees.
Boonop is dit ook moontlik om die lys van kexts wat 'n beleid geconfigureer het, te verkry deur die struktuur _mac_policy_list
uit geheue te dump wat met elke geregistreerde beleid opgedateer word.
MACF Inisialiserings
MACF word baie vroeg geinitialiseer. Dit word opgestel in XNU se bootstrap_thread
: na ipc_bootstrap
'n oproep na mac_policy_init()
wat die mac_policy_list
inisialiseer en 'n oomblik later word mac_policy_initmach()
aangeroep. Onder andere dinge sal hierdie funksie al die Apple kexts met die AppleSecurityExtension
sleutel in hul Info.plist soos ALF.kext
, AppleMobileFileIntegrity.kext
, Quarantine.kext
, Sandbox.kext
en TMSafetyNet.kext
verkry en laai.
MACF Oproepe
Dit is algemeen om oproepe na MACF in kode te vind soos: #if CONFIG_MAC
voorwaardelike blokke. Boonop is dit binne hierdie blokke moontlik om oproepe na mac_proc_check*
te vind wat MACF aanroep om toestemmings te kontroleer om sekere aksies uit te voer. Boonop is die formaat van die MACF oproepe: mac_<object>_<opType>_opName
.
Die objek is een van die volgende: bpfdesc
, cred
, file
, proc
, vnode
, mount
, devfs
, ifnet
, inpcb
, mbuf
, ipq
, pipe
, sysv[msg/msq/shm/sem]
, posix[shm/sem]
, socket
, kext
.
Die opType
is gewoonlik check wat gebruik sal word om die aksie toe te laat of te weier. Dit is egter ook moontlik om notify
te vind, wat die kext sal toelaat om op die gegewe aksie te reageer.
Jy kan 'n voorbeeld vind in 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 */
[...]
Dan is dit moontlik om die kode van mac_file_check_mmap
te vind in https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/security/mac_file.c#L174
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;
}
Wat die MAC_CHECK
makro aanroep, waarvan die kode in https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/security/mac_internal.h#L261 gevind kan word.
/*
* 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)
Welke sal oor al die geregistreerde mac beleid gaan en hul funksies aanroep en die uitvoer binne die fout veranderlike stoor, wat slegs deur mac_error_select
oorruilbaar sal wees deur sukses kodes, so as enige kontrole misluk, sal die volledige kontrole misluk en die aksie nie toegelaat word nie.
tip
Onthou egter dat nie alle MACF aanroep slegs gebruik word om aksies te weier nie. Byvoorbeeld, mac_priv_grant
roep die makro MAC_GRANT aan, wat die aangevraagde voorreg sal toeken as enige beleid met 'n 0 antwoord:
/*
* MAC_GRANT voer die aangewese kontrole uit deur die beleid
* module lys te loop en met elkeen te kontroleer hoe dit oor die
* versoek voel. Anders as MAC_CHECK, grant dit as enige beleid '0' teruggee,
* en andersins terugkeer EPERM. Let daarop dat dit sy waarde via
* 'error' in die omvang van die oproeper teruggee.
*/
#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)
priv_check & priv_grant
Hierdie aanroepe is bedoel om te kontroleer en te verskaf (tens of) voorregte gedefinieer in bsd/sys/priv.h.
Sommige kernkode sal priv_check_cred()
van bsd/kern/kern_priv.c aanroep met die KAuth akrediteer van die proses en een van die voorregte kode wat mac_priv_check
sal aanroep om te sien of enige beleid die voorreg weier en dan roep dit mac_priv_grant
aan om te sien of enige beleid die voorreg
toeken.
proc_check_syscall_unix
Hierdie haak laat toe om alle stelsels aanroepe te onderskep. In bsd/dev/[i386|arm]/systemcalls.c
is dit moontlik om die verklaarde funksie unix_syscall
te sien, wat hierdie kode bevat:
#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 */
Wat die oproepende proses bitmask sal nagaan of die huidige syscall mac_proc_check_syscall_unix
moet aanroep. Dit is omdat syscalls so gereeld aangeroep word dat dit interessant is om te probeer om mac_proc_check_syscall_unix
nie elke keer aan te roep nie.
Let daarop dat die funksie proc_set_syscall_filter_mask()
, wat die bitmask syscalls in 'n proses stel, deur Sandbox aangeroep word om masks op gesandboksde prosesse te stel.
Blootgestelde MACF syscalls
Dit is moontlik om met MACF te kommunikeer deur sommige syscalls wat in security/mac.h gedefinieer is:
/*
* 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*/
Verwysings
tip
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.