
CVE-2023-41992(macOSカーネルの脆弱性)の概念実証。悪用手法を実証し、パッチ分析を提供します。
これはCVE-2023-41992の概念実証です。まず第一に、これは__脱獄__とはまったく関係ありません!そして、まだ開発中です。
これまでに助けてくれたすべての人に感謝します。プライバシーの理由から、ここに名前を挙げないかもしれません。希望があれば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] はサードパーティアプリのサンドボックス内ではタスクをkillしません。以前mach_thread_self()を選んだのは、それが私が見つけられた唯一のピン止めされたsend rightだったからです。
しかし、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ポートガード例外をトリガーしたすべてのタスクがkillされます。しかし...
Fatal Mach port guards - always delivered synchronously.
バグをトリガーするスレッドに対してスレッド例外ポートを設定し、例外通知を処理しないようにすればよいのです。カーネルはここで返答を待つだけで、SIGKILLは発生しません。
ipc_right_copyout()内でNULLエントリによるパニックです。