
macOS 커널 취약점인 CVE-2023-41992에 대한 개념 증명으로, 악용 기술을 시연하고 패치 분석을 제공합니다.
이것은 CVE-2023-41992에 대한 개념 증명입니다. 그리고 무엇보다도, 이것은 __jailbreak__와는 전혀 관련이 없습니다! 그리고 아직 개발 중입니다.
지금까지 도와주신 모든 분들께 감사드립니다. 개인정보 보호를 위해 여기에 이름을 적지 않을 수 있습니다. 원하시면 DM 보내주세요!
내가 알기로는 패치는 ipc_right_destroy에 있습니다. 누군가 X(또는 Twitter)에서 이것을 지적했습니다.
diff --git a/osfmk/ipc/ipc_right.c b/osfmk/ipc/ipc_right.c
index a81ac21..32a9a3e 100644
--- a/osfmk/ipc/ipc_right.c
+++ b/osfmk/ipc/ipc_right.c
@@ -912,7 +912,6 @@ ipc_right_destroy(
mach_port_type_t type;
bits = entry->ie_bits;
- entry->ie_bits &= ~IE_BITS_TYPE_MASK;
type = IE_BITS_TYPE(bits);
assert(is_active(space));
ipc_right_destroy를 사용하여 ipc 공간에 남아 있는 none 타입 ipc 항목을 얻으면 예외가 발생합니다. 아래 [0]과 [1]을 확인하세요.
kern_return_t
ipc_right_destroy(
ipc_space_t space,
mach_port_name_t name,
ipc_entry_t entry,
boolean_t check_guard,
uint64_t guard)
{
...
if (type == MACH_PORT_TYPE_SEND) {
if (ip_is_pinned(port)) {
assert(ip_active(port));
is_write_unlock(space);
mach_port_guard_exception_pinned(space, // <---- [0]
name, port, MPG_FLAGS_MOD_REFS_PINNED_DESTROY);
return KERN_INVALID_CAPABILITY;
}
ipc_hash_delete(space, ip_to_object(port), name, entry);
}
...
if ((type & MACH_PORT_TYPE_RECEIVE) &&
(check_guard) && (port->ip_guarded) &&
(guard != port->ip_context)) {
/* Guard Violation */
uint64_t portguard = port->ip_context;
ip_mq_unlock(port);
is_write_unlock(space);
/* Raise mach port guard exception */
mach_port_guard_exception(name, // <---- [1]
0, portguard, kGUARD_EXC_DESTROY);
return KERN_INVALID_RIGHT;
}
[0]은 서드파티 앱 샌드박스에서 태스크를 종료하지 않습니다. 이전에 mach_thread_self()를 선택한 이유는 그것이 내가 찾을 수 있는 유일한 고정된 전송 권리였기 때문입니다.
하지만 ReportCrash 또는 SIGKILL을 피하지 않으면, 이 버그는 WebContent 샌드박스에서 유용하지 않습니다. 그래서 조금 더 깊이 파고들었습니다.
void
mach_port_guard_ast(thread_t t,
mach_exception_data_type_t code, mach_exception_data_type_t subcode)
{
...
if (reason <= MAX_FATAL_kGUARD_EXC_CODE) {
/*
* Fatal Mach port guards - always delivered synchronously.
* Check if anyone has registered for Synchronous EXC_GUARD, if yes then,
* deliver it synchronously and then kill the process, else kill the process
* and deliver the exception via EXC_CORPSE_NOTIFY.
*/
if (task_exception_notify(EXC_GUARD, code, subcode) == KERN_SUCCESS) {
task_bsdtask_kill(task);
} else {
exit_with_guard_exception(get_bsdtask_info(task), code, subcode);
}
...
커널의 mach_port_guard_ast는 mach 포트 가드 예외를 처리합니다. 치명적인 예외의 경우, 먼저 예외 포트를 찾습니다. 예외 알림이 KERN_SUCCESS를 반환하면 SIGKILL을 수행합니다. 유망해 보입니다. 치명적인 mach 포트 가드 예외를 발생시킨 모든 태스크가 종료됩니다. 하지만...
Fatal Mach port guards - always delivered synchronously.
버그를 트리거하는 스레드에 대해 스레드 예외 포트를 설정하고, 예외 알림을 처리하지 않으면 됩니다. 커널은 여기서 응답을 기다리기만 하므로 SIGKILL이 발생하지 않습니다.
NULL 항목으로 ipc_right_copyout()에서 패닉 발생.