hacktricks/macos-hardening/macos-security-and-privileg.../macos-proces-abuse/macos-ipc-inter-process-com.../macos-xpc/macos-xpc-connecting-proces.../macos-xpc_connection_get_au...

18 KiB
Raw Blame History

macOS xpc_connection_get_audit_token 攻撃

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

この技術はhttps://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/ からコピーされました

Machメッセージの基本情報

Machメッセージが何であるかわからない場合は、次のページをチェックしてください

{% content-ref url="../../../../mac-os-architecture/macos-ipc-inter-process-communication/" %} macos-ipc-inter-process-communication {% endcontent-ref %}

当面は、次のことを覚えておいてください:
Machメッセージは、machカーネルに組み込まれた単一の受信者、複数の送信者の通信チャネルである_machポート_を介して送信されます。複数のプロセスがmachポートにメッセージを送信できますが、いつでも単一のプロセスがそれを読み取ることができます。ファイルディスクリプタやソケットと同様に、machポートはカーネルによって割り当てられ、管理され、プロセスは整数しか見えず、それを使用してカーネルに使用するmachポートを示すことができます。

XPC接続

XPC接続の確立方法を知らない場合は、次を確認してください

{% content-ref url="../" %} .. {% endcontent-ref %}

脆弱性の概要

あなたが知るべき興味深いことは、XPCの抽象化は1対1の接続であるが、複数の送信者を持つことができる技術に基づいているということです。

  • Machポートは単一の受信者、_複数の送信者_です。
  • XPC接続の監査トークンは、_最後に受信したメッセージからコピーされた監査トークン_です。
  • XPC接続の監査トークンを取得することは、多くのセキュリティチェックにとって重要です。

前述の状況は有望に聞こえますが、問題が発生しないシナリオもあります:

  • 監査トークンは、接続を受け入れるかどうかを決定するための認可チェックによく使用されます。これはサービスポートへのメッセージを使用して行われるため、まだ接続が確立されていません。このポートへの追加のメッセージは、追加の接続要求として処理されます。したがって、接続を受け入れる前のチェックは脆弱ではありません(これは、-listener:shouldAcceptNewConnection:内では監査トークンが安全であることを意味します)。したがって、特定のアクションを検証するXPC接続を探しています
  • XPCイベントハンドラは同期的に処理されます。つまり、1つのメッセージのイベントハンドラが完了する前に、次のメッセージのイベントハンドラを呼び出す必要があります。したがって、XPCイベントハンドラ内では、監査トークンは他の通常の非応答メッセージによって上書きされることはありません

これに基づいて、2つの異なる方法が考えられます

  1. Variant1:
  • ExploitはサービスAとサービスB接続します。
  • サービスBは、ユーザーができない特権機能をサービスAで呼び出すことができます。
  • サービスAは、イベントハンドラ内ではない状態で**xpc_connection_get_audit_token**を呼び出します。
  • したがって、異なるメッセージが監査トークンを上書きする可能性があります。なぜなら、イベントハンドラの外部で非同期にディスパッチされるからです。
  • Exploitは、サービスAへのSEND権限をサービスBに渡します
  • したがって、svc Bは実際にはサービスAメッセージを送信します。
  • Exploitは特権アクションを呼び出そうとします。RC svc Aは、このアクションの認可をチェックしますが、svc Bは監査トークンを上書きしているためExploitが特権アクションを呼び出すためのアクセスを提供する、Exploitは特権アクションを呼び出すことができます。
  1. Variant 2:
  • サービスBは、ユーザーができない特権機能をサービスAで呼び出すことができます。
  • Exploitは、サービスAに接続し、特定のリプライポート応答を期待するメッセージを送信します。
  • Exploitは、サービスBにメッセージを送信し、そのリプライポートを渡します。
  • サービスBが応答すると、メッセージをサービスAに送信しますが、同時にExploitは別のメッセージをサービスAに送信**し、特権機能に到達しようとし、サービスBからの応答が監査トークンを完璧なタイミングで上書きすることを期待します競合状態

Variant 1: イベントハンドラの外でxpc_connection_get_audit_tokenを呼び出す

シナリオ:

  • 2つのmach サービスABに接続できる(サンドボックスプロファイルと接続を受け入れる前の認証チェックに基づく)。
  • Aは、Bが渡すことができる特定のアクションの****認証チェック**を持っている必要があります(ただし、私たちのアプリはできません)。
  • たとえば、Bにはいくつかのエンタイトルメントがあるか、rootとして実行されている場合、特権アクションを実行するようにAに要求することができます。
  • この認証チェックでは、Aは非同期に監査トークンを取得します。たとえば、dispatch_asyncからxpc_connection_get_audit_tokenを呼び出すことによって。

{% hint style="danger" %} この場合、攻撃者はレースコンディションをトリガーし、BがAにアクションを実行するようにexploitを複数回要求します。RCが成功するとBの監査トークンメモリにコピーされますexploitのリクエストがAによって処理される間に、それによってBだけが要求できる特権アクションにアクセスできます。 {% endhint %}

これは、A**がsmd**として、Bdiagnosticdとして発生しました。SMJobBless関数は、特権ヘルパーツール(rootとして)をインストールするために使用できます。rootとして実行されるプロセスがsmd**に連絡する場合、他のチェックは実行されません。

したがって、サービスBは**diagnosticdであり、rootとして実行されるため、プロセスのモニタリング**に使用できます。モニタリングが開始されると、1秒に複数のメッセージを送信します。

攻撃を実行するには:

  1. 通常のXPCプロトコルに従って、smdへの接続を確立します。
  2. 次に、diagnosticdへの接続を確立しますが、新しいmachポートを2つ生成してそれらを送信する代わりに、クライアントポートの送信権を**smdへの接続に対して持っている送信権のコピー**で置き換えます。
  3. これは、**diagnosticdにXPCメッセージを送信できるが、diagnosticdが送信するメッセージはsmd**に送信されることを意味します。
  • smdにとって、私たちとdiagnosticdの両方のメッセージは同じ接続に到着します。
  1. diagnosticdに私たち(またはアクティブな任意の)プロセスのモニタリングを開始するように依頼し、smdに対してルーチン1004のメッセージをスパムします(特権ツールをインストールするため)。
  2. これにより、handle_blessで非常に特定のウィンドウに到達する必要があるレースコンディションが作成されます。特権ヘルパーツールはアプリのバンドルにありますので、xpc_connection_get_pidへの呼び出しが自分自身のプロセスのPIDを返す必要があります。ただし、connection_is_authorized関数内のxpc_connection_get_audit_tokenへの呼び出しは、diganosticdの監査トークンを使用する必要があります。

Variant 2: 返信の転送

前述のように、XPC接続のイベントハンドラは複数回同時に実行されません。ただし、XPC返信メッセージは異なる方法で処理されます。返信が期待されるメッセージを送信するための2つの関数が存在します。

  • void xpc_connection_send_message_with_reply(xpc_connection_t connection, xpc_object_t message, dispatch_queue_t replyq, xpc_handler_t handler)は、XPCメッセージが指定されたキューで受信および解析される場合です。
  • xpc_object_t xpc_connection_send_message_with_reply_sync(xpc_connection_t connection, xpc_object_t message)は、XPCメッセージが現在のディスパッチキューで受信および解析される場合です。

したがって、XPC返信パケットはXPCイベントハンドラの実行中に解析される可能性があります。_xpc_connection_set_credsはロックを使用していますが、これは監査トークンの一部の上書きを防ぐだけであり、接続オブジェクト全体をロックしません。そのため、パケットの解析とイベントハンドラの実行の間に監査トークンを置き換えることが可能です。

このシナリオでは、次のものが必要です:

  • 先ほどと同様に、私たちが両方に接続できる2つのmachサービス_A_と_B_が必要です。
  • 再び、_A_は_B_が渡すことができる特定のアクションの認証チェックを持っている必要がありますただし、私たちのアプリはできません
  • _A_は返信を期待するメッセージを私たちに送信します。
  • _B_に返信するメッセージを送信できます。

_A_が返信を期待するメッセージを送信するのを待ちます1、返信せずに返信ポートを取得し、_B_に送信するメッセージに使用します2。その後、禁止されたアクションを使用するメッセージを送信し、_B_からの返信と同時に到着することを期待します3

発見の問題

他のインスタンスを見つけるために長い時間を費やしましたが、条件が静的または動的に検索するのが難しかったです。xpc_connection_get_audit_tokenへの非同期呼び出しを検索するために、Fridaを使用してこの関数にフックし、バックトレースに_xpc_connection_mach_eventが含まれているかどうかをチェックしましたこれはイベントハンドラから呼び出されていないことを意味します。ただし、これは現在フックしているプロセスとアクティブに使用されているアクションからの呼び出しのみを検出します。IDA/Ghidraで到達可能なすべてのmachサービスを分析することは非常に時間がかかりましたが、特にdyld共有キャッシュが関与する呼び出しの場合です。dispatch_asyncを使用して提出されたブロックから到達可能なxpc_connection_get_audit_tokenへの呼び出しを検索するためにスクリプトを試しましたが、ブロックとdyld共有キャッシュへのパースが困難でした。これにしばらく時間を費やした後、私たちは持っているものを提出する方が良いと判断しました。

修正策

最終的に、私たちはsmdの一般的な問題と具体的な問題を報告しました。Appleはsmdのみ修正し、xpc_connection_get_audit_tokenの呼び出しをxpc_dictionary_get_audit_tokenに置き換えました。

関数xpc_dictionary_get_audit_tokenは、このXPCメッセージが受信されたマッハメッセージから監査トークンをコピーします。つまり、脆弱性はありません。ただし、xpc_dictionary_get_audit_tokenと同様に、これは公開APIの一部ではありません。より高レベルのNSXPCConnection APIでは、現在のメッセージの監査トークンを取得する明確な方法は存在しません。なぜなら、これはすべてのメッセージをメソッド呼び出しに抽象化しているからです。

なぜAppleがより一般的な修正を適用しなかったのかは不明です。たとえば、接続の保存された監査トークンと一致しないメッセージを破棄するという方法が考えられます。プロセスの監査トークンが正当に変更されるが、接続は開いたままにする必要があるシナリオがあるかもしれませんたとえば、setuidを呼び出すとUIDフィールドが変更されます。ただし、異なるPIDやPIDバージョンのような変更は意図されていない可能性が高いです。

いずれにせよ、この問題はiOS 17とmacOS 14でもまだ残っているため、見つけるために頑張ってください

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥