macOS xpc_connection_get_audit_token Attack
Reading time: 12 minutes
tip
Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le đŹ groupe Discord ou le groupe telegram ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépÎts github.
For further information check the original post: https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/. This is a summary:
Mach Messages Basic Info
If you don't know what Mach Messages are start checking this page:
macOS IPC - Inter Process Communication
For the moment remember that (definition from here):
Mach messages are sent over a mach port, which is a single receiver, multiple sender communication channel built into the mach kernel. Multiple processes can send messages to a mach port, but at any point only a single process can read from it. Just like file descriptors and sockets, mach ports are allocated and managed by the kernel and processes only see an integer, which they can use to indicate to the kernel which of their mach ports they want to use.
XPC Connection
If you don't know how a XPC connection is established check:
Vuln Summary
What is interesting for you to know is that XPCâs abstraction is a one-to-one connection, but it is based on top of a technology which can have multiple senders, so:
- Mach ports are single receiver, multiple sender.
- An XPC connectionâs audit token is the audit token of copied from the most recently received message.
- Obtaining the audit token of an XPC connection is critical to many security checks.
Although the previous situation sounds promising there are some scenarios where this is not going to cause problems (from here):
- Audit tokens are often used for an authorization check to decide whether to accept a connection. As this happens using a message to the service port, there is no connection established yet. More messages on this port will just be handled as additional connection requests. So any checks before accepting a connection are not vulnerable (this also means that within
-listener:shouldAcceptNewConnection:
the audit token is safe). We are therefore looking for XPC connections that verify specific actions. - XPC event handlers are handled synchronously. This means that the event handler for one message must be completed before calling it for the next one, even on concurrent dispatch queues. So inside an XPC event handler the audit token can not be overwritten by other normal (non-reply!) messages.
Two different methods this might be exploitable:
- Variant1:
- Exploit connects to service A and service B
- Service B can call a privileged functionality in service A that the user cannot
- Service A calls
xpc_connection_get_audit_token
while not inside the event handler for a connection in adispatch_async
. - So a different message could overwrite the Audit Token because it's being dispatched asynchronously outside of the event handler.
- The exploit passes to service B the SEND right to service A.
- So svc B will be actually sending the messages to service A.
- The exploit tries to call the privileged action. In a RC svc A checks the authorization of this action while svc B overwrote the Audit token (giving the exploit access to call the privileged action).
- Variant 2:
- Service B can call a privileged functionality in service A that the user cannot
- Exploit connects with service A which sends the exploit a message expecting a response in a specific replay port.
- Exploit sends service B a message passing that reply port.
- When service B replies, it sends the message to service A, while the exploit sends a different message to service A trying to reach a privileged functionality and expecting that the reply from service B will overwrite the Audit token in the perfect moment (Race Condition).
Variant 1: calling xpc_connection_get_audit_token outside of an event handler
Scenario:
- Two mach services
A
andB
that we can both connect to (based on the sandbox profile and the authorization checks before accepting the connection). - A must have an authorization check for a specific action that
B
can pass (but our app canât). - For example, if B has some entitlements or is running as root, it might allow him to ask A to perform a privileged action.
- For this authorization check,
A
obtains the audit token asynchronously, for example by callingxpc_connection_get_audit_token
fromdispatch_async
.
caution
In this case an attacker could trigger a Race Condition making a exploit that asks A to perform an action several times while making B send messages to A
. When the RC is successful, the audit token of B will be copied in memory while the request of our exploit is being handled by A, giving it access to the privilege action only B could request.
This happened with A
as smd
and B
as diagnosticd
. The function SMJobBless
from smb an be used to install a new privileged helper toot (as root). If a process running as root contact smd, no other checks will be performed.
Therefore, the service B is diagnosticd
because it runs as root and can be used to monitor a process, so once monitoring has started, it will send multiple messages per second.
To perform the attack:
- Initiate a connection to the service named
smd
using the standard XPC protocol. - Form a secondary connection to
diagnosticd
. Contrary to normal procedure, rather than creating and sending two new mach ports, the client port send right is substituted with a duplicate of the send right associated with thesmd
connection. - As a result, XPC messages can be dispatched to
diagnosticd
, but responses fromdiagnosticd
are rerouted tosmd
. Tosmd
, it appears as though the messages from both the user anddiagnosticd
are originating from the same connection.
- The next step involves instructing
diagnosticd
to initiate monitoring of a chosen process (potentially the user's own). Concurrently, a flood of routine 1004 messages is sent tosmd
. The intent here is to install a tool with elevated privileges. - This action triggers a race condition within the
handle_bless
function. The timing is critical: thexpc_connection_get_pid
function call must return the PID of the user's process (as the privileged tool resides in the user's app bundle). However, thexpc_connection_get_audit_token
function, specifically within theconnection_is_authorized
subroutine, must reference the audit token belonging todiagnosticd
.
Variant 2: reply forwarding
In an XPC (Cross-Process Communication) environment, although event handlers don't execute concurrently, the handling of reply messages has a unique behavior. Specifically, two distinct methods exist for sending messages that expect a reply:
xpc_connection_send_message_with_reply
: Here, the XPC message is received and processed on a designated queue.xpc_connection_send_message_with_reply_sync
: Conversely, in this method, the XPC message is received and processed on the current dispatch queue.
This distinction is crucial because it allows for the possibility of reply packets being parsed concurrently with the execution of an XPC event handler. Notably, while _xpc_connection_set_creds
does implement locking to safeguard against the partial overwrite of the audit token, it does not extend this protection to the entire connection object. Consequently, this creates a vulnerability where the audit token can be replaced during the interval between the parsing of a packet and the execution of its event handler.
To exploit this vulnerability, the following setup is required:
- Two mach services, referred to as
A
andB
, both of which can establish a connection. - Service
A
should include an authorization check for a specific action that onlyB
can perform (the user's application cannot). - Service
A
should send a message that anticipates a reply. - The user can send a message to
B
that it will respond to.
The exploitation process involves the following steps:
- Wait for service
A
to send a message that expects a reply. - Instead of replying directly to
A
, the reply port is hijacked and used to send a message to serviceB
. - Subsequently, a message involving the forbidden action is dispatched, with the expectation that it will be processed concurrently with the reply from
B
.
Below is a visual representation of the described attack scenario:
 (1) (1) (1) (1) (1) (1).png)
.png)
Discovery Problems
- Difficulties in Locating Instances: Searching for instances of
xpc_connection_get_audit_token
usage was challenging, both statically and dynamically. - Methodology: Frida was employed to hook the
xpc_connection_get_audit_token
function, filtering calls not originating from event handlers. However, this method was limited to the hooked process and required active usage. - Analysis Tooling: Tools like IDA/Ghidra were used for examining reachable mach services, but the process was time-consuming, complicated by calls involving the dyld shared cache.
- Scripting Limitations: Attempts to script the analysis for calls to
xpc_connection_get_audit_token
fromdispatch_async
blocks were hindered by complexities in parsing blocks and interactions with the dyld shared cache.
The fix
- Reported Issues: A report was submitted to Apple detailing the general and specific issues found within
smd
. - Apple's Response: Apple addressed the issue in
smd
by substitutingxpc_connection_get_audit_token
withxpc_dictionary_get_audit_token
. - Nature of the Fix: The
xpc_dictionary_get_audit_token
function is considered secure as it retrieves the audit token directly from the mach message tied to the received XPC message. However, it's not part of the public API, similar toxpc_connection_get_audit_token
. - Absence of a Broader Fix: It remains unclear why Apple didn't implement a more comprehensive fix, such as discarding messages not aligning with the saved audit token of the connection. The possibility of legitimate audit token changes in certain scenarios (e.g.,
setuid
usage) might be a factor. - Current Status: The issue persists in iOS 17 and macOS 14, posing a challenge for those seeking to identify and understand it.
Finding vulnerable code paths in practice (2024â2025)
When auditing XPC services for this bug class, focus on authorization performed outside the messageâs event handler or concurrently with reply processing.
Static triage hints:
- Search for calls to
xpc_connection_get_audit_token
reachable from blocks queued viadispatch_async
/dispatch_after
or other worker queues that run outside the message handler. - Look for authorization helpers that mix per-connection and per-message state (e.g., fetch PID from
xpc_connection_get_pid
but audit token fromxpc_connection_get_audit_token
). - In NSXPC code, verify that checks are done in
-listener:shouldAcceptNewConnection:
or, for per-message checks, that the implementation uses a per-message audit token (e.g., the messageâs dictionary viaxpc_dictionary_get_audit_token
in lower-level code).
Dynamic triage tips:
- Hook
xpc_connection_get_audit_token
and flag invocations whose user stack does not include the event-delivery path (e.g.,_xpc_connection_mach_event
). Example Frida hook:
Interceptor.attach(Module.getExportByName(null, 'xpc_connection_get_audit_token'), {
onEnter(args) {
const bt = Thread.backtrace(this.context, Backtracer.ACCURATE)
.map(DebugSymbol.fromAddress).join('\n');
if (!bt.includes('_xpc_connection_mach_event')) {
console.log('[!] xpc_connection_get_audit_token outside handler\n' + bt);
}
}
});
Remarques :
- Sur macOS, instrumenter des binaires protégés d'Apple peut nécessiter de désactiver SIP ou d'utiliser un environnement de développement ; préférez tester vos propres builds ou des services userland.
- Pour reply-forwarding races (Variant 2), surveillez l'analyse concurrente des reply packets en fuzzant les timings de
xpc_connection_send_message_with_reply
par rapport aux requĂȘtes normales et vĂ©rifiez si l'audit token effectif utilisĂ© pendant l'autorisation peut ĂȘtre influencĂ©.
Primitives d'exploitation dont vous aurez probablement besoin
- Multi-sender setup (Variant 1) : créez des connexions vers A et B ; dupliquez le send right du client port de A et utilisez-le comme client port de B afin que les replies de B soient livrés à A.
// Duplicate a SEND right you already hold
mach_port_t dup;
mach_port_insert_right(mach_task_self(), a_client, a_client, MACH_MSG_TYPE_MAKE_SEND);
dup = a_client; // use `dup` when crafting Bâs connect packet instead of a fresh client port
- Reply hijack (Variant 2) : capturer le send-once right depuis la requĂȘte en attente d'A (reply port), puis envoyer un message façonnĂ© Ă B en utilisant ce reply port afin que la rĂ©ponse de B atterrisse sur A pendant que votre requĂȘte privilĂ©giĂ©e est analysĂ©e.
Ces attaques nécessitent la création de messages mach au bas niveau pour le bootstrap XPC et les formats de message ; consultez les pages d'introduction mach/XPC dans cette section pour les agencements exacts des paquets et les flags.
Useful tooling
- XPC sniffing/dynamic inspection : gxpc (open-source XPC sniffer) peut aider à énumérer les connexions et observer le trafic pour valider les configurations multi-sender et le timing. Exemple :
gxpc -p <PID> --whitelist <service-name>
. - Classic dyld interposing for libxpc : interposer sur
xpc_connection_send_message*
etxpc_connection_get_audit_token
pour enregistrer les points d'appel et les traces de pile lors de tests black-box.
References
- Sector 7 â Donât Talk All at Once! Elevating Privileges on macOS by Audit Token Spoofing: https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/
- Apple â About the security content of macOS Ventura 13.4 (CVEâ2023â32405): https://support.apple.com/en-us/106333
tip
Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le đŹ groupe Discord ou le groupe telegram ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépÎts github.