macOS MACF
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
๊ธฐ๋ณธ ์ ๋ณด
MACF๋ ์ด์์ฒด์ ์ ๋ด์ฅ๋ ๋ณด์ ์์คํ ์ธ **Mandatory Access Control Framework(๊ฐ์ ์ ๊ทผ ์ ์ด ํ๋ ์์ํฌ)**์ ์ฝ์์ ๋๋ค. ์ด ์์คํ ์ ํ์ผ, ์ ํ๋ฆฌ์ผ์ด์ ๋ฐ ์์คํ ๋ฆฌ์์ค์ ๊ฐ์ ์์คํ ์ ํน์ ๋ถ๋ถ์ ๋๊ฐ ๋๋ ๋ฌด์์ด ์ ๊ทผํ ์ ์๋์ง์ ๋ํ ์๊ฒฉํ ๊ท์น์ ์ค์ ํ์ฌ ์ปดํจํฐ๋ฅผ ๋ณดํธํ๋ ์ญํ ์ ํฉ๋๋ค. ์ด๋ฌํ ๊ท์น์ ์๋์ผ๋ก ์ ์ฉํจ์ผ๋ก์จ MACF๋ ๊ถํ์ด ์๋ ์ฌ์ฉ์์ ํ๋ก์ธ์ค๋ง ํน์ ์์ ์ ์ํํ ์ ์๋๋ก ํ์ฌ ๋ฌด๋จ ์ ๊ทผ์ด๋ ์ ์์ ํ๋์ ์ํ์ ์ค์ ๋๋ค.
MACF๋ ์ค์ ๋ก ๊ฒฐ์ ์ ๋ด๋ฆฌ์ง ์๊ณ ๋จ์ํ ๋์์ **๊ฐ๋ก์ฑ๋ค(intercepts)**๋ ์ ์ ์ ์ํ์ธ์. ์ค์ ๊ฒฐ์ ์ AppleMobileFileIntegrity.kext, Quarantine.kext, Sandbox.kext, TMSafetyNet.kext ๋ฐ mcxalr.kext์ ๊ฐ์ด ํธ์ถ๋๋ policy modules(kernel extensions)์ ์ํด ๋ด๋ ค์ง๋๋ค.
- ์ ์ฑ ์ ์งํํ ์ ์๋ค (return 0 non-zero on some operation)
- ์ ์ฑ ์ ๋ชจ๋ํฐ๋งํ ์ ์๋ค (return 0, so as not to object but piggyback on hook to do something)
- MACF static policy๋ ๋ถํ ์ ์ค์น๋๋ฉฐ ์ ๋ ์ ๊ฑฐ๋์ง ์๋๋ค
- MACF dynamic policy๋ KEXT(kextload)์ ์ํด ์ค์น๋๋ฉฐ ์ด๋ก ์ ์ผ๋ก๋ kextunloaded๋ ์ ์๋ค
- iOS์์๋ static policy๋ง ํ์ฉ๋๋ฉฐ macOS์์๋ static + dynamic์ด ํ์ฉ๋๋ค
- https://newosxbook.com/xxr/index.php
ํ๋ฆ
- ํ๋ก์ธ์ค๊ฐ syscall/mach trap์ ์ํํ๋ค
- ๊ด๋ จ ํจ์๊ฐ kernel ๋ด๋ถ์์ ํธ์ถ๋๋ค
- ํจ์๊ฐ MACF๋ฅผ ํธ์ถํ๋ค
- MACF๋ ํด๋น ํจ์์ ํ ์ ์์ฒญํ ์ ์ฑ ๋ชจ๋๋ค์ ํ์ธํ๋ค
- MACF๊ฐ ๊ด๋ จ ์ ์ฑ ๋ค์ ํธ์ถํ๋ค
- ์ ์ฑ ๋ค์ด ํด๋น ๋์์ ํ์ฉํ ์ง ๊ฑฐ๋ถํ ์ง ํ์ํ๋ค
Caution
Apple๋ง MAC Framework KPI๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ณดํต MACF๋ก ๊ถํ์ ํ์ธํ๋ ํจ์๋ค์ ๋งคํฌ๋ก MAC_CHECK๋ฅผ ํธ์ถํฉ๋๋ค. ์๋ฅผ ๋ค์ด ์์ผ์ ์์ฑํ๋ syscall์ ๊ฒฝ์ฐ mac_socket_check_create๋ฅผ ํธ์ถํ๊ณ , ์ด ํจ์๋ MAC_CHECK(socket_check_create, cred, domain, type, protocol);์ ํธ์ถํฉ๋๋ค. ๋ํ ๋งคํฌ๋ก MAC_CHECK๋ security/mac_internal.h์ ๋ค์๊ณผ ๊ฐ์ด ์ ์๋์ด ์์ต๋๋ค:
Resolver tambien MAC_POLICY_ITERATE, MAC_CHECK_CALL, MAC_CHECK_RSLT
#define MAC_CHECK(check, args...) do { \
error = 0; \
MAC_POLICY_ITERATE({ \
if (mpc->mpc_ops->mpo_ ## check != NULL) { \
MAC_CHECK_CALL(check, mpc); \
int __step_err = mpc->mpc_ops->mpo_ ## check (args); \
MAC_CHECK_RSLT(check, mpc); \
error = mac_error_select(__step_err, error); \
} \
}); \
} while (0)
์ฐธ๊ณ ๋ก check๋ฅผ socket_check_create๋ก, args...๋ฅผ (cred, domain, type, protocol)๋ก ๋ณํํ๋ฉด:
// Note the "##" just get the param name and append it to the prefix
#define MAC_CHECK(socket_check_create, args...) do { \
error = 0; \
MAC_POLICY_ITERATE({ \
if (mpc->mpc_ops->mpo_socket_check_create != NULL) { \
MAC_CHECK_CALL(socket_check_create, mpc); \
int __step_err = mpc->mpc_ops->mpo_socket_check_create (args); \
MAC_CHECK_RSLT(socket_check_create, mpc); \
error = mac_error_select(__step_err, error); \
} \
}); \
} while (0)
๋์ฐ๋ฏธ ๋งคํฌ๋ก๋ฅผ ํ์ฅํ๋ฉด ๊ตฌ์ฒด์ ์ธ ์ ์ด ํ๋ฆ์ด ๋ํ๋ฉ๋๋ค:
do { // MAC_CHECK
error = 0;
do { // MAC_POLICY_ITERATE
struct mac_policy_conf *mpc;
u_int i;
for (i = 0; i < mac_policy_list.staticmax; i++) {
mpc = mac_policy_list.entries[i].mpc;
if (mpc == NULL) {
continue;
}
if (mpc->mpc_ops->mpo_socket_check_create != NULL) {
DTRACE_MACF3(mac__call__socket_check_create,
void *, mpc, int, error, int, MAC_ITERATE_CHECK); // MAC_CHECK_CALL
int __step_err = mpc->mpc_ops->mpo_socket_check_create(args);
DTRACE_MACF2(mac__rslt__socket_check_create,
void *, mpc, int, __step_err); // MAC_CHECK_RSLT
error = mac_error_select(__step_err, error);
}
}
if (mac_policy_list_conditional_busy() != 0) {
for (; i <= mac_policy_list.maxindex; i++) {
mpc = mac_policy_list.entries[i].mpc;
if (mpc == NULL) {
continue;
}
if (mpc->mpc_ops->mpo_socket_check_create != NULL) {
DTRACE_MACF3(mac__call__socket_check_create,
void *, mpc, int, error, int, MAC_ITERATE_CHECK);
int __step_err = mpc->mpc_ops->mpo_socket_check_create(args);
DTRACE_MACF2(mac__rslt__socket_check_create,
void *, mpc, int, __step_err);
error = mac_error_select(__step_err, error);
}
}
mac_policy_list_unbusy();
}
} while (0);
} while (0);
๋ค์ ๋งํด, MAC_CHECK(socket_check_create, ...)๋ ๋จผ์ ์ ์ ์ ์ฑ
์ ์ํํ๊ณ , ์กฐ๊ฑด์ ์ผ๋ก ์ ๊ธ์ ์ค์ ํ์ฌ ๋์ ์ ์ฑ
์ ๋ฐ๋ณตํ๋ฉฐ, ๊ฐ hook ์ฃผ์์ DTrace ํ๋ก๋ธ๋ฅผ ๋ฐ์์ํค๊ณ , ๋ชจ๋ hook์ ๋ฐํ ์ฝ๋๋ฅผ mac_error_select()๋ฅผ ํตํด ๋จ์ผ error ๊ฒฐ๊ณผ๋ก ๋ณํฉํฉ๋๋ค.
Labels
MACF๋ ์ ์ฑ
์ด ํน์ ์ ๊ทผ์ ํ์ฉํ ์ง ์ฌ๋ถ๋ฅผ ๊ฒ์ฌํ ๋ ์ฌ์ฉํ๋ labels๋ฅผ ์ฌ์ฉํฉ๋๋ค. labels ๊ตฌ์กฐ์ฒด ์ ์ธ ์ฝ๋๋ found here, ์ด๋ here์ struct ucred ๋ด๋ถ cr_label ๋ถ๋ถ์์ ์ฌ์ฉ๋ฉ๋๋ค. ๋ผ๋ฒจ์ ํ๋๊ทธ์ ์ผ์ ์์ slots๋ฅผ ํฌํจํ๋ฉฐ, ์ด๋ MACF policies to allocate pointers๊ฐ ํฌ์ธํฐ๋ฅผ ํ ๋นํ๋ ๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด Sanbox๋ ์ปจํ
์ด๋ ํ๋กํ์ ๊ฐ๋ฆฌํต๋๋ค
MACF Policies
MACF Policy๋ ํน์ ์ปค๋ ์์ ์ ์ ์ฉ๋ ๊ท์น๊ณผ ์กฐ๊ฑด์ ์ ์ํฉ๋๋ค.
์ปค๋ ํ์ฅ(kernel extension)์ mac_policy_conf struct๋ฅผ ๊ตฌ์ฑํ ๋ค์ mac_policy_register๋ฅผ ํธ์ถํ์ฌ ๋ฑ๋กํ ์ ์์ต๋๋ค. From here:
#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 */
};
์ด ์ ์ฑ
๋ค์ ๊ตฌ์ฑํ๋ ์ปค๋ ์ต์คํ
์
์ mac_policy_register ํธ์ถ์ ํ์ธํ๋ฉด ์ฝ๊ฒ ์๋ณํ ์ ์์ต๋๋ค. ๋ํ ์ต์คํ
์
์ ๋์ค์ด์
๋ธ์ ํ์ธํ๋ฉด ์ฌ์ฉ๋ mac_policy_conf ๊ตฌ์กฐ์ฒด๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.
MACF ์ ์ฑ ์ ๋์ ์ผ๋ก ๋ฑ๋ก ๋ฐ ๋ฑ๋ก ํด์ ๋ ์ ์๋ค๋ ์ ์ ์ ์ํ์ธ์.
mac_policy_conf์ ์ฃผ์ ํ๋ ์ค ํ๋๋ **mpc_ops**์
๋๋ค. ์ด ํ๋๋ ์ ์ฑ
์ด ๊ด์ฌ ์๋ ์ฐ์ฐ๋ค์ ์ง์ ํฉ๋๋ค. ์๋ฐฑ ๊ฐ์ ์ฐ์ฐ์ด ์๊ธฐ ๋๋ฌธ์, ๋ชจ๋ ํญ๋ชฉ์ 0์ผ๋ก ์ด๊ธฐํํ ๋ค์ ์ ์ฑ
์ด ๊ด์ฌ ์๋ ํญ๋ชฉ๋ง ์ ํํ ์ ์์ต๋๋ค. ์์ธํ ๋ด์ฉ์ ์ฌ๊ธฐ:
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;
[...]
๊ฑฐ์ ๋ชจ๋ ํ
์ ํด๋น ์์
๋ค ์ค ํ๋๊ฐ ๊ฐ๋ก์ฑ์ง ๋ MACF์ ์ํด ์ฝ๋ฐฑ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ mpo_policy_* ํ
๋ค์ ์์ธ์ธ๋ฐ, ์ด๋ mpo_hook_policy_init()๊ฐ ๋ฑ๋ก ์(์ฆ mac_policy_register() ์ดํ) ํธ์ถ๋๋ ์ฝ๋ฐฑ์ด๊ณ mpo_hook_policy_initbsd()๋ BSD ์๋ธ์์คํ
์ด ์ ๋๋ก ์ด๊ธฐํ๋ ํ ๋ฆ์ ๋ฑ๋ก ์์ ํธ์ถ๋๊ธฐ ๋๋ฌธ์
๋๋ค.
๋ํ, mpo_policy_syscall ํ
์ ์ด๋ค kext๋ private ioctl ์คํ์ผ ํธ์ถ interface๋ฅผ ๋
ธ์ถํ๊ธฐ ์ํด ๋ฑ๋กํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ฉด user client๋ ์ ์ํ code์ ์ ํ์ arguments๋ฅผ ํฌํจํด policy name์ ํ๋ผ๋ฏธํฐ๋ก ์ง์ ํ์ฌ mac_syscall (#381)์ ํธ์ถํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, **Sandbox.kext**๊ฐ ์ด๋ฅผ ๋ง์ด ์ฌ์ฉํฉ๋๋ค.
kext์ **__DATA.__const***๋ฅผ ํ์ธํ๋ฉด ์ ์ฑ
์ ๋ฑ๋กํ ๋ ์ฌ์ฉ๋ mac_policy_ops ๊ตฌ์กฐ์ฒด๋ฅผ ์๋ณํ ์ ์์ต๋๋ค. ์ด๋ ํด๋น ํฌ์ธํฐ๊ฐ mpo_policy_conf ๋ด๋ถ์ ์คํ์
์ ์์นํด ์๊ณ , ๊ทธ ์์ญ์ ์กด์ฌํ๋ NULL ํฌ์ธํฐ์ ๊ฐ์๋ก๋ ์ฐพ์ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
๋ํ, ๋ฑ๋ก๋ ๊ฐ ์ ์ฑ
๋ง๋ค ์
๋ฐ์ดํธ๋๋ ๊ตฌ์กฐ์ฒด **_mac_policy_list**๋ฅผ ๋ฉ๋ชจ๋ฆฌ์์ ๋คํํ๋ฉด ์ ์ฑ
์ ๊ตฌ์ฑํ kext๋ค์ ๋ชฉ๋ก์ ์ป์ ์ ์์ต๋๋ค.
์์คํ
์ ๋ฑ๋ก๋ ๋ชจ๋ ์ ์ฑ
์ ๋คํํ๋ ค๋ฉด ๋๊ตฌ xnoop์ ์ฌ์ฉํ ์๋ ์์ต๋๋ค:
xnoop offline .
Xn๐p> macp
mac_policy_list(@0xfffffff0447159b8): 3 Mac Policies@0xfffffff0447153f0
0: 0xfffffff044886f18:
mpc_name: AppleImage4
mpc_fullName: AppleImage4 hooks
mpc_ops: mac_policy_ops@0xfffffff044886f68
1: 0xfffffff0448d7d40:
mpc_name: AMFI
mpc_fullName: Apple Mobile File Integrity
mpc_ops: mac_policy_ops@0xfffffff0448d72c8
2: 0xfffffff044b0b950:
mpc_name: Sandbox
mpc_fullName: Seatbelt sandbox policy
mpc_ops: mac_policy_ops@0xfffffff044b0b9b0
Xn๐p> dump mac_policy_opns@0xfffffff0448d72c8
Type 'struct mac_policy_opns' is unrecognized - dumping as raw 64 bytes
Dumping 64 bytes from 0xfffffff0448d72c8
๊ทธ๋ฐ ๋ค์ check policy์ ๋ชจ๋ ์ฒดํฌ๋ฅผ ๋ค์์ผ๋ก ๋คํํฉ๋๋ค:
Xn๐p> dump mac_policy_ops@0xfffffff044b0b9b0
Dumping 2696 bytes from 0xfffffff044b0b9b0 (as struct mac_policy_ops)
mpo_cred_check_label_update_execve(@0x30): 0xfffffff046d7fb54(PACed)
mpo_cred_check_label_update(@0x38): 0xfffffff046d7348c(PACed)
mpo_cred_label_associate(@0x58): 0xfffffff046d733f0(PACed)
mpo_cred_label_destroy(@0x68): 0xfffffff046d733e4(PACed)
mpo_cred_label_update_execve(@0x90): 0xfffffff046d7fb60(PACed)
mpo_cred_label_update(@0x98): 0xfffffff046d73370(PACed)
mpo_file_check_fcntl(@0xe8): 0xfffffff046d73164(PACed)
mpo_file_check_lock(@0x110): 0xfffffff046d7309c(PACed)
mpo_file_check_mmap(@0x120): 0xfffffff046d72fc4(PACed)
mpo_file_check_set(@0x130): 0xfffffff046d72f2c(PACed)
mpo_reserved08(@0x168): 0xfffffff046d72e3c(PACed)
mpo_reserved09(@0x170): 0xfffffff046d72e34(PACed)
mpo_necp_check_open(@0x1f0): 0xfffffff046d72d9c(PACed)
mpo_necp_check_client_action(@0x1f8): 0xfffffff046d72cf8(PACed)
mpo_vnode_notify_setextattr(@0x218): 0xfffffff046d72ca4(PACed)
mpo_vnode_notify_setflags(@0x220): 0xfffffff046d72c84(PACed)
mpo_proc_check_get_task_special_port(@0x250): 0xfffffff046d72b98(PACed)
mpo_proc_check_set_task_special_port(@0x258): 0xfffffff046d72ab4(PACed)
mpo_vnode_notify_unlink(@0x268): 0xfffffff046d72958(PACed)
mpo_vnode_check_copyfile(@0x290): 0xfffffff046d726c0(PACed)
mpo_mount_check_quotactl(@0x298): 0xfffffff046d725c4(PACed)
...
XNU์์์ MACF ์ด๊ธฐํ
์ด๊ธฐ ๋ถํธ์คํธ๋ฉ๊ณผ mac_policy_init()
- MACF๋ ๋งค์ฐ ์ด๊ธฐ ๋จ๊ณ์์ ์ด๊ธฐํ๋ฉ๋๋ค. XNU ์์ ์ฝ๋์
bootstrap_thread์์ipc_bootstrap์ดํ์ XNU๋mac_policy_init()์ ํธ์ถํฉ๋๋ค(mac_base.c). mac_policy_init()์ ์ ์ญmac_policy_list(์ ์ฑ ์ฌ๋กฏ์ ๋ฐฐ์ด ๋๋ ๋ฆฌ์คํธ)๋ฅผ ์ด๊ธฐํํ๊ณ XNU ๋ด๋ถ์์ MAC(Mandatory Access Control) ์ธํ๋ผ๋ฅผ ์ค์ ํฉ๋๋ค.- ์ดํ
mac_policy_initmach()์ด ํธ์ถ๋์ด ๋ด์ฅ๋๊ฑฐ๋ ๋ฒ๋ค๋ ์ ์ฑ ๋ค์ ์ปค๋ ์ธก ๋ฑ๋ก์ ์ฒ๋ฆฌํฉ๋๋ค.
mac_policy_initmach()์ โsecurity extensionsโ ๋ก๋ฉ
-
mac_policy_initmach()์ ์ฌ์ ๋ก๋๋(๋๋ โpolicy injectionโ ๋ฆฌ์คํธ์ ์๋) kernel extension(kext)์ ๊ฒ์ฌํ๊ณ ํด๋น Info.plist์์AppleSecurityExtensionํค๋ฅผ ํ์ธํฉ๋๋ค. -
Info.plist์
<key>AppleSecurityExtension</key>(๋๋true)๋ฅผ ์ ์ธํ kext๋ค์ โ๋ณด์ ํ์ฅโ์ผ๋ก ๊ฐ์ฃผ๋ฉ๋๋ค โ ์ฆ MAC ์ ์ฑ ์ ๊ตฌํํ๊ฑฐ๋ MACF ์ธํ๋ผ์ ํ ์ ๊ฑฐ๋ ๊ฒ๋ค์ ๋๋ค. -
๊ทธ ํค๋ฅผ ํฌํจํ๋ Apple kext์ ์๋ก๋ ALF.kext, AppleMobileFileIntegrity.kext (AMFI), Sandbox.kext, Quarantine.kext, TMSafetyNet.kext, CoreTrust.kext, AppleSystemPolicy.kext ๋ฑ์ด ์์ต๋๋ค(๋ฑ๋ฑ).
-
์ปค๋์ ์ด๋ฌํ kext๋ค์ด ์กฐ๊ธฐ์ ๋ก๋๋๋๋ก ๋ณด์ฅํ ๋ค ๋ถํ ์ค์ ์ด๋ค์ ๋ฑ๋ก ๋ฃจํด์ ํธ์ถ(
mac_policy_register๋ฅผ ํตํด)ํ์ฌmac_policy_list์ ์ฝ์ ํฉ๋๋ค. -
๊ฐ ์ ์ฑ ๋ชจ๋(kext)์ ํ ๋ค(
mpc_ops)์ ํฌํจํmac_policy_conf๊ตฌ์กฐ์ฒด๋ฅผ ์ ๊ณตํ๋ฉฐ, ์ด๋ ๋ค์ํ MAC ์์ (vnode ๊ฒ์ฌ, exec ๊ฒ์ฌ, ๋ผ๋ฒจ ์ ๋ฐ์ดํธ ๋ฑ)์ ์ฒ๋ฆฌํฉ๋๋ค. -
๋ก๋ ์ ํ๋๊ทธ์๋
MPC_LOADTIME_FLAG_NOTLATE์ ๊ฐ์ด โ์กฐ๊ธฐ์ ๋ก๋๋์ด์ผ ํจโ์ ์๋ฏธํ๋ ๊ฐ์ด ์์ ์ ์์ผ๋ฉฐ(๋ฐ๋ผ์ ๋ฆ์ ๋ฑ๋ก ์๋๊ฐ ๊ฑฐ๋ถ๋ฉ๋๋ค)โฆ -
๋ฑ๋ก์ด ์๋ฃ๋๋ฉด ๊ฐ ๋ชจ๋์ ํธ๋ค์ ๋ฐ๊ณ
mac_policy_list์ ์ฌ๋กฏ์ ์ฐจ์งํฉ๋๋ค. -
์ดํ MAC ํ (์: vnode ์ ๊ทผ, exec ๋ฑ)์ด ํธ์ถ๋ ๋ MACF๋ ๋ฑ๋ก๋ ๋ชจ๋ ์ ์ฑ ์ ์ํํ์ฌ ๊ณต๋ ๊ฒฐ์ ์ ๋ด๋ฆฝ๋๋ค.
-
ํนํ AMFI(Apple Mobile File Integrity)๋ ์ด๋ฌํ ๋ณด์ ํ์ฅ ์ค ํ๋์ ๋๋ค. ํด๋น kext์ Info.plist์๋ ๋ณด์ ์ ์ฑ ์์ ํ์ํ๋
AppleSecurityExtensionํค๊ฐ ํฌํจ๋์ด ์์ต๋๋ค. -
์ปค๋ ๋ถํ ์ ์ผํ์ผ๋ก ์ปค๋ ๋ก๋ ๋ก์ง์ ๋ง์ ์๋ธ์์คํ ์ด ์์กดํ๊ธฐ ์ ์ โ๋ณด์ ์ ์ฑ โ(AMFI ๋ฑ)์ด ์ด๋ฏธ ํ์ฑํ๋์ด ์๋๋ก ๋ณด์ฅํฉ๋๋ค. ์๋ฅผ ๋ค์ด ์ปค๋์ โ์์ผ๋ก์ ์์ ์ ์ํด AppleMobileFileIntegrity (AMFI), Sandbox, Quarantine ์ ์ฑ ์ ํฌํจํ โฆ ๋ณด์ ์ ์ฑ ์ ๋ก๋ํจ์ผ๋ก์จ ์ค๋นํ๋คโ๊ณ ํฉ๋๋ค.
cd /System/Library/Extensions
find . -name Info.plist | xargs grep AppleSecurityExtension 2>/dev/null
./AppleImage4.kext/Contents/Info.plist: <key>AppleSecurityExtension</key>
./ALF.kext/Contents/Info.plist: <key>AppleSecurityExtension</key>
./CoreTrust.kext/Contents/Info.plist: <key>AppleSecurityExtension</key>
./AppleMobileFileIntegrity.kext/Contents/Info.plist: <key>AppleSecurityExtension</key>
./Quarantine.kext/Contents/Info.plist: <key>AppleSecurityExtension</key>
./Sandbox.kext/Contents/Info.plist: <key>AppleSecurityExtension</key>
./AppleSystemPolicy.kext/Contents/Info.plist: <key>AppleSecurityExtension</key>
KPI ์ข ์์ฑ ๋ฐ MAC ์ ์ฑ kext์์์ com.apple.kpi.dsep
MAC ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ๋ kext๋ฅผ ์์ฑํ ๋(์: mac_policy_register() ๋ฑ ํธ์ถ), kext ๋ง์ปค(kxld)๊ฐ ํด๋น ์ฌ๋ณผ์ ํด์ํ ์ ์๋๋ก KPI(Kernel Programming Interfaces)์ ๋ํ ์ข
์์ฑ์ ์ ์ธํด์ผ ํฉ๋๋ค. ๋ฐ๋ผ์ kext๊ฐ MACF์ ์์กดํจ์ ์ ์ธํ๋ ค๋ฉด Info.plist์ com.apple.kpi.dsep๋ฅผ ๋ช
์ํด์ผ ํฉ๋๋ค(find . Info.plist | grep AppleSecurityExtension). ๊ทธ๋ฌ๋ฉด kext๋ mac_policy_register, mac_policy_unregister ๋ฐ MAC ํ
ํจ์ ํฌ์ธํฐ์ ๊ฐ์ ์ฌ๋ณผ์ ์ฐธ์กฐํ๊ฒ ๋ฉ๋๋ค. ์ด๋ฌํ ์ฌ๋ณผ์ ํด๊ฒฐํ๋ ค๋ฉด com.apple.kpi.dsep๋ฅผ ์ข
์์ฑ์ผ๋ก ๋์ดํด์ผ ํฉ๋๋ค.
Example Info.plist snippet (inside your .kext):
<key>OSBundleLibraries</key>
<dict>
<key>com.apple.kpi.dsep</key>
<string>18.0</string>
<key>com.apple.kpi.libkern</key>
<string>18.0</string>
<key>com.apple.kpi.bsd</key>
<string>18.0</string>
<key>com.apple.kpi.mach</key>
<string>18.0</string>
โฆ (other kpi dependencies as needed)
</dict>
MACF ํธ์ถ
์ฝ๋์์ #if CONFIG_MAC ๊ฐ์ ์กฐ๊ฑด ๋ธ๋ก ์์ MACF์ ๋ํ ํธ์ถ์ด ์ ์๋ ๊ฒ์ ํํ ๋ณผ ์ ์์ต๋๋ค. ๋ํ, ์ด๋ฌํ ๋ธ๋ก ๋ด๋ถ์์๋ ํน์ ์์
์ ์ํํ ๊ถํ์ ํ์ธํ๊ธฐ ์ํด MACF๋ฅผ ํธ์ถํ๋ mac_proc_check* ๊ฐ์ ํธ์ถ์ ์ฐพ์ ์ ์์ต๋๋ค. MACF ํธ์ถ์ ํ์์ ๋ณดํต mac_<object>_<opType>_opName ์
๋๋ค.
๊ฐ์ฒด(object)๋ ๋ค์ ์ค ํ๋์
๋๋ค: bpfdesc, cred, file, proc, vnode, mount, devfs, ifnet, inpcb, mbuf, ipq, pipe, sysv[msg/msq/shm/sem], posix[shm/sem], socket, kext.opType์ ๋ณดํต ์์
์ ํ์ฉํ๊ฑฐ๋ ๊ฑฐ๋ถํ๋ ๋ฐ ์ฌ์ฉ๋๋ check ์
๋๋ค. ๊ทธ๋ฌ๋ ์ฃผ์ด์ง ๋์์ ๋ํด kext๊ฐ ๋ฐ์ํ๋๋ก ํ์ฉํ๋ notify๋ฅผ ์ฐพ์ ์๋ ์์ต๋๋ค.
You can find an example 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 */
[...]
๊ทธ ๋ค์ mac_file_check_mmap์ ์ฝ๋๋ 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;
}
์ด๋ MAC_CHECK ๋งคํฌ๋ก๋ฅผ ํธ์ถํ๋ฉฐ, ํด๋น ์ฝ๋๋ https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/security/mac_internal.h#L261์์ ํ์ธํ ์ ์์ต๋๋ค.
/*
* 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)
์ด ๋งคํฌ๋ก๋ ๋ฑ๋ก๋ ๋ชจ๋ mac ์ ์ฑ
์ ์ํํ๋ฉด์ ๊ฐ ์ ์ฑ
์ ํจ์๋ฅผ ํธ์ถํ๊ณ ๊ทธ ์ถ๋ ฅ์ error ๋ณ์์ ์ ์ฅํฉ๋๋ค. ์ด error ๊ฐ์ ์ฑ๊ณต ์ฝ๋์ ์ํด mac_error_select๋ก๋ง ์ฌ์ ์๋ ์ ์์ผ๋ฏ๋ก, ์ด๋ค ๊ฒ์ฌ๋ผ๋ ์คํจํ๋ฉด ์ ์ฒด ๊ฒ์ฌ๊ฐ ์คํจํ๊ณ ํด๋น ์์
์ ํ์ฉ๋์ง ์์ต๋๋ค.
Tip
ํ์ง๋ง ๋ชจ๋ MACF ์ฝ์์์ด ๋์์ ๊ฑฐ๋ถํ๊ธฐ ์ํด์๋ง ์ฌ์ฉ๋๋ ๊ฒ์ ์๋๋ผ๋ ์ ์ ๊ธฐ์ตํ์ธ์. ์๋ฅผ ๋ค์ด,
mac_priv_grant๋ ๋งคํฌ๋ก MAC_GRANT๋ฅผ ํธ์ถํ๋๋ฐ, ์ด ๋งคํฌ๋ก๋ ์ด๋ค ์ ์ฑ ์ด๋ผ๋ 0์ ๋ฐํํ๋ฉด ์์ฒญ๋ ๊ถํ์ ๋ถ์ฌํฉ๋๋ค:/* * 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)
priv_check & priv_grant
These callas are meant to check and provide (tens of) ๊ถํ defined in bsd/sys/priv.h.
์ผ๋ถ ์ปค๋ ์ฝ๋๋ ํ๋ก์ธ์ค์ KAuth ์๊ฒฉ์ฆ๋ช
๊ณผ ๊ถํ ์ฝ๋ ์ค ํ๋๋ฅผ ๊ฐ์ง๊ณ bsd/kern/kern_priv.c์ priv_check_cred()๋ฅผ ํธ์ถํฉ๋๋ค. ์ด ํธ์ถ์ mac_priv_check๋ฅผ ํธ์ถํด ์ด๋ค ์ ์ฑ
์ด ๊ถํ ๋ถ์ฌ๋ฅผ ๊ฑฐ๋ถํ๋์ง ํ์ธํ๊ณ , ๊ทธ ๋ค์ mac_priv_grant๋ฅผ ํธ์ถํด ์ด๋ค ์ ์ฑ
์ด ํด๋น privilege๋ฅผ ๋ถ์ฌํ๋์ง ํ์ธํฉ๋๋ค.
proc_check_syscall_unix
This hook allows to intercept all system calls. In bsd/dev/[i386|arm]/systemcalls.c itโs possible to see the declared function unix_syscall, which contains this code:
#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 */
์ด๋ ํธ์ถ ์ค์ธ ํ๋ก์ธ์ค์ bitmask์์ ํ์ฌ syscall์ด mac_proc_check_syscall_unix๋ฅผ ํธ์ถํด์ผ ํ๋์ง๋ฅผ ํ์ธํ๋ค. syscalls๋ ๋งค์ฐ ์์ฃผ ํธ์ถ๋๋ฏ๋ก ๋งค๋ฒ mac_proc_check_syscall_unix๋ฅผ ํธ์ถํ๋ ๊ฒ์ ํผํ๋ ๊ฒ์ด ์ ๋ฆฌํ๋ค.
์ฐธ๊ณ ๋ก ํ๋ก์ธ์ค์ bitmask syscalls๋ฅผ ์ค์ ํ๋ ํจ์ proc_set_syscall_filter_mask()๋ Sandbox๊ฐ sandboxed processes์ ๋ง์คํฌ๋ฅผ ์ค์ ํ ๋ ํธ์ถ๋๋ค.
๋ ธ์ถ๋ MACF syscalls
์ผ๋ถ syscalls๋ฅผ ํตํด MACF์ ์ํธ์์ฉํ ์ ์์ผ๋ฉฐ, ์ด๋ security/mac.h์ ์ ์๋์ด ์๋ค:
/*
* 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*/
์ฐธ๊ณ ์๋ฃ
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


