
Prova de conceito para CVE-2023-41992, uma vulnerabilidade do kernel macOS, demonstrando técnicas de exploração e fornecendo uma análise de patch.
Este é uma prova de conceito para CVE-2023-41992. E antes de tudo, isso não tem nada a ver com jailbreak! E ainda está em desenvolvimento.
Agradeço a todos que me ajudaram até agora. Por questões de privacidade, posso não listá-los aqui. Envie-me um DM se quiser!
Pelo que sei, a correção está em ipc_right_destroy. Alguém também apontou isso no X (ou 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));
Usar ipc_right_destroy para obter uma entrada ipc de tipo 'none' deixada no espaço ipc pode desencadear uma exceção. Veja [0] e [1] abaixo.
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] não matará a tarefa na sandbox de aplicativos de terceiros. Escolhi mach_thread_self() antes porque era o único direito de envio fixado que consegui encontrar.
Mas sem evitar ReportCrash ou SIGKILL, o bug não será útil na sandbox do WebContent. Então pesquisei um pouco mais.
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 no kernel lida com exceções de guarda de porta mach. Para uma exceção fatal, primeiro procura a porta de exceção. Se a notificação de exceção retornar KERN_SUCCESS, realiza um SIGKILL. Parece promissor, toda tarefa que desencadeou uma exceção fatal de guarda de porta mach será morta. No entanto...
Fatal Mach port guards - always delivered synchronously.
Eu posso simplesmente definir uma porta de exceção de thread para a thread que desencadeia o bug, e não processar a notificação de exceção. O kernel vai apenas esperar por uma resposta aqui, sem SIGKILL.
Pânico em ipc_right_copyout() com uma entrada NULL.