macOS xpc_connection_get_audit_token Επίθεση
Reading time: 13 minutes
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Για περισσότερες πληροφορίες ελέγξτε την αρχική ανάρτηση: https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/. Αυτή είναι μια περίληψη:
Mach Messages Basic Info
Εάν δεν ξέρετε τι είναι τα Mach Messages ξεκινήστε ελέγχοντας αυτή τη σελίδα:
macOS IPC - Inter Process Communication
Προς το παρόν θυμηθείτε ότι (definition from here):
Τα Mach messages αποστέλλονται μέσω ενός mach port, το οποίο είναι ένα κανάλι επικοινωνίας single receiver, multiple sender ενσωματωμένο στον mach kernel. Πολλές διεργασίες μπορούν να στείλουν μηνύματα σε ένα mach port, αλλά ανά πάσα στιγμή μόνο μία διεργασία μπορεί να διαβάσει από αυτό. Όπως τα file descriptors και τα sockets, τα mach ports διατίθενται και διαχειρίζονται από τον kernel και οι διεργασίες βλέπουν μόνο έναν ακέραιο, που μπορούν να χρησιμοποιήσουν για να υποδείξουν στον kernel ποιο από τα mach ports τους θέλουν να χρησιμοποιήσουν.
XPC Connection
Εάν δεν γνωρίζετε πώς γίνεται η δημιουργία μιας σύνδεσης XPC δείτε:
Vuln Summary
Είναι χρήσιμο να γνωρίζετε ότι η abstraction του XPC είναι μια σύνδεση one-to-one, αλλά βασίζεται πάνω σε μια τεχνολογία που μπορεί να έχει multiple senders, οπότε:
- Τα Mach ports είναι single receiver, multiple sender.
- Το audit token μιας XPC connection είναι το audit token που αντιγράφεται από το πιο πρόσφατα ληφθέν μήνυμα.
- Η απόκτηση του audit token μιας XPC connection είναι κρίσιμη για πολλούς έλεγχους ασφαλείας.
Αν και η παραπάνω κατάσταση φαίνεται προβληματική, υπάρχουν σενάρια όπου αυτό δεν θα προκαλέσει προβλήματα (from here):
- Τα audit tokens συχνά χρησιμοποιούνται για έναν έλεγχο εξουσιοδότησης για να αποφασίσουν αν θα αποδεχτούν μια σύνδεση. Καθώς αυτό γίνεται χρησιμοποιώντας ένα μήνυμα προς το service port, δεν υπάρχει ακόμη καθορισμένη σύνδεση. Περισσότερα μηνύματα σε αυτή την πόρτα απλά θα χειριστούν ως πρόσθετα αιτήματα σύνδεσης. Οπότε οποιοιδήποτε έλεγχοι πριν την αποδοχή μιας σύνδεσης δεν είναι ευάλωτοι (αυτό σημαίνει επίσης ότι μέσα σε
-listener:shouldAcceptNewConnection:
το audit token είναι ασφαλές). Αναζητούμε λοιπόν XPC connections που επαληθεύουν συγκεκριμένες ενέργειες. - Οι XPC event handlers χειρίζονται συγχρονισμένα. Αυτό σημαίνει ότι ο event handler για ένα μήνυμα πρέπει να ολοκληρωθεί πριν κληθεί για το επόμενο, ακόμα και σε concurrent dispatch queues. Επομένως, μέσα σε έναν XPC event handler το audit token δεν μπορεί να αντικατασταθεί από άλλα κανονικά (μη-reply!) μηνύματα.
Δύο διαφορετικές μέθοδοι που αυτό μπορεί να είναι εκμεταλλεύσιμο:
- Variant1:
- Το Exploit connects στο service A και στο service B
- Το Service B μπορεί να καλέσει μια privileged functionality στο service A που ο χρήστης δεν μπορεί
- Το Service A καλεί
xpc_connection_get_audit_token
ενώ δεν βρίσκεται μέσα στον event handler για μια σύνδεση, αλλά σε έναdispatch_async
. - Έτσι, ένα διαφορετικό μήνυμα θα μπορούσε να επαναγράψει το Audit Token επειδή γίνεται dispatch ασύγχρονα εκτός του event handler.
- Το exploit περνάει στο service B το SEND right του service A.
- Οπότε το svc B θα στέλνει πρακτικά τα μηνύματα στο service A.
- Το exploit προσπαθεί να καλέσει τη privileged action. Σε μια RC το svc A ελέγχει την εξουσιοδότηση αυτής της ενέργειας ενώ svc B έχει αντικαταστήσει το Audit token (δίνοντας στο exploit πρόσβαση να καλέσει την privileged ενέργεια).
- Variant 2:
- Το Service B μπορεί να καλέσει μια privileged functionality στο service A που ο χρήστης δεν μπορεί
- Το Exploit συνδέεται με το service A το οποίο στέλνει στο exploit ένα μήνυμα που αναμένει απάντηση σε μια συγκεκριμένη reply port.
- Το Exploit στέλνει στο service B ένα μήνυμα περνώντας εκείνη την reply port.
- Όταν το service B απαντήσει, στέλνει το μήνυμα στο service A, ενώ το exploit στέλνει διαφορετικό μήνυμα στο service A προσπαθώντας να προσεγγίσει μια privileged functionality και αναμένοντας ότι η απάντηση από το service B θα αντικαταστήσει το Audit token τη σωστή στιγμή (Race Condition).
Variant 1: calling xpc_connection_get_audit_token outside of an event handler
Σενάριο:
- Δύο mach services
A
καιB
στα οποία μπορούμε και οι δύο να συνδεθούμε (βασισμένο στο sandbox profile και τους ελέγχους εξουσιοδότησης πριν την αποδοχή της σύνδεσης). - Ο A πρέπει να έχει έναν έλεγχο εξουσιοδότησης για μια συγκεκριμένη ενέργεια που
B
μπορεί να περάσει (αλλά η εφαρμογή μας όχι). - Για παράδειγμα, αν το B έχει κάποια entitlements ή τρέχει ως root, μπορεί να του επιτρέπει να ζητήσει από το A να εκτελέσει μια privileged ενέργεια.
- Για αυτόν τον έλεγχο εξουσιοδότησης, το
A
παίρνει το audit token ασύγχρονα, για παράδειγμα καλώνταςxpc_connection_get_audit_token
απόdispatch_async
.
caution
Σε αυτή την περίπτωση ένας attacker θα μπορούσε να προκαλέσει ένα Race Condition δημιουργώντας ένα exploit που ζητά από το A να εκτελέσει μια ενέργεια πολλές φορές ενώ κάνει B να στέλνει μηνύματα στο A
. Όταν η RC είναι επιτυχής, το audit token του B θα αντιγραφεί στη μνήμη ενώ το αίτημα του exploit χειρίζεται από το A, δίνοντας σε αυτό πρόσβαση στην privileged ενέργεια που μόνο το B θα μπορούσε να ζητήσει.
Αυτό συνέβη με το A
ως smd
και το B
ως diagnosticd
. Η συνάρτηση SMJobBless
από smb μπορεί να χρησιμοποιηθεί για να εγκαταστήσει ένα νέο privileged helper tool (ως root). Αν μια process που τρέχει ως root επικοινωνήσει με το smd, δεν θα γίνουν άλλοι έλεγχοι.
Επομένως, το service B είναι diagnosticd
επειδή τρέχει ως root και μπορεί να χρησιμοποιηθεί για να monitor μια διεργασία, έτσι μόλις ξεκινήσει το monitoring, θα στέλνει πολλαπλά μηνύματα ανά δευτερόλεπτο.
Για να εκτελέσετε την επίθεση:
- Ξεκινήστε μια σύνδεση προς το service με όνομα
smd
χρησιμοποιώντας το standard XPC protocol. - Δημιουργήστε μια δευτερεύουσα σύνδεση προς το
diagnosticd
. Αντί για την κανονική διαδικασία, αντί να δημιουργηθούν και να αποσταλούν δύο νέα mach ports, το client port send right αντικαθίσταται με ένα αντίγραφο του send right που σχετίζεται με τη σύνδεσηsmd
. - Ως αποτέλεσμα, XPC μηνύματα μπορούν να διαβιβαστούν στο
diagnosticd
, αλλά οι απαντήσεις από τοdiagnosticd
παρακάμπτονται προς τοsmd
. Για τοsmd
, φαίνεται σαν τα μηνύματα τόσο από τον χρήστη όσο και από τοdiagnosticd
να προέρχονται από την ίδια σύνδεση.
- Το επόμενο βήμα περιλαμβάνει την εντολή στο
diagnosticd
να ξεκινήσει monitoring μιας επιλεγμένης διεργασίας (πιθανώς της δικής του εφαρμογής). Ταυτόχρονα, στέλνεται ένας κατακλυσμός από ρουτίνες 1004 μηνυμάτων στοsmd
. Ο σκοπός εδώ είναι να εγκατασταθεί ένα εργαλείο με αυξημένα προνόμια. - Αυτή η ενέργεια πυροδοτεί ένα race condition μέσα στη συνάρτηση
handle_bless
. Ο χρονισμός είναι κρίσιμος: η κλήση τηςxpc_connection_get_pid
πρέπει να επιστρέψει το PID της διεργασίας του χρήστη (εφόσον το privileged tool βρίσκεται στο user app bundle). Ωστόσο, ηxpc_connection_get_audit_token
συγκεκριμένα, εντός της υπορουτίναςconnection_is_authorized
, πρέπει να αναφέρεται στο audit token που ανήκει στοdiagnosticd
.
Variant 2: reply forwarding
Σε ένα XPC (Cross-Process Communication) περιβάλλον, αν και οι event handlers δεν τρέχουν ταυτόχρονα, ο χειρισμός των reply μηνυμάτων έχει μια μοναδική συμπεριφορά. Συγκεκριμένα, υπάρχουν δύο διακριτοί τρόποι για την αποστολή μηνυμάτων που αναμένουν απάντηση:
xpc_connection_send_message_with_reply
: Εδώ, το XPC μήνυμα λαμβάνεται και επεξεργάζεται σε μια καθορισμένη queue.xpc_connection_send_message_with_reply_sync
: Αντίθετα, σε αυτή τη μέθοδο, το XPC μήνυμα λαμβάνεται και επεξεργάζεται στην τρέχουσα dispatch queue.
Αυτή η διάκριση είναι κρίσιμη επειδή επιτρέπει την πιθανότητα για reply packets να αναλυθούν ταυτόχρονα με την εκτέλεση ενός XPC event handler. Σημειωτέον, ενώ _xpc_connection_set_creds
εφαρμόζει locking για να προστατεύσει από μερική επανεγγραφή του audit token, δεν επεκτείνει αυτή την προστασία σε ολόκληρο το αντικείμενο σύνδεσης. Επομένως, αυτό δημιουργεί μια ευπάθεια όπου το audit token μπορεί να αντικατασταθεί στο διάστημα μεταξύ της ανάλυσης ενός πακέτου και της εκτέλεσης του event handler του.
Για να εκμεταλλευτείτε αυτή την ευπάθεια απαιτείται το ακόλουθο setup:
- Δύο mach services, αναφερόμενα ως
A
καιB
, και τα δύο μπορούν να δημιουργήσουν σύνδεση. - Το service
A
θα πρέπει να περιλαμβάνει έναν έλεγχο εξουσιοδότησης για μια συγκεκριμένη ενέργεια που μόνο τοB
μπορεί να πραγματοποιήσει (η εφαρμογή του χρήστη δεν μπορεί). - Το service
A
θα πρέπει να στείλει ένα μήνυμα που αναμένει απάντηση. - Ο χρήστης μπορεί να στείλει ένα μήνυμα στο
B
στο οποίο αυτό θα απαντήσει.
Η διαδικασία εκμετάλλευσης περιλαμβάνει τα εξής βήματα:
- Περιμένετε το service
A
να στείλει ένα μήνυμα που περιμένει απάντηση. - Αντί να απαντήσετε απευθείας στο
A
, η reply port υπεξαιρείται και χρησιμοποιείται για να σταλεί ένα μήνυμα στο serviceB
. - Στη συνέχεια, αποστέλλεται ένα μήνυμα που αφορά την απαγορευμένη ενέργεια, με την προσδοκία ότι θα επεξεργαστεί ταυτόχρονα με την απάντηση από το
B
.
Below is a visual representation of the described attack scenario:
 (1) (1) (1) (1) (1) (1).png)
.png)
Discovery Problems
- Δυσκολίες στην Εντοπισμό Περιπτώσεων: Η αναζήτηση για περιπτώσεις χρήσης του
xpc_connection_get_audit_token
ήταν δύσκολη, τόσο στατικά όσο και δυναμικά. - Μεθοδολογία: Χρησιμοποιήθηκε Frida για να γίνει hook στη συνάρτηση
xpc_connection_get_audit_token
, φιλτράροντας κλήσεις που δεν προέρχονταν από event handlers. Ωστόσο, αυτή η μέθοδος περιοριζόταν στη hooked process και απαιτούσε ενεργή χρήση. - Εργαλεία Ανάλυσης: Εργαλεία όπως IDA/Ghidra χρησιμοποιήθηκαν για την εξέταση reachable mach services, αλλά η διαδικασία ήταν χρονοβόρα, περίπλοκη λόγω κλήσεων που εμπλέκουν το dyld shared cache.
- Περιορισμοί Σκριπτινγκ: Οι προσπάθειες να αυτοματοποιηθεί η ανάλυση για κλήσεις σε
xpc_connection_get_audit_token
μέσα σεdispatch_async
blocks επηρεάστηκαν από την πολυπλοκότητα στην ανάλυση των blocks και τις αλληλεπιδράσεις με το dyld shared cache.
The fix
- Αναφερόμενα Θέματα: Υποβλήθηκε αναφορά στην Apple που περιέγραφε τα γενικά και ειδικά ζητήματα που βρέθηκαν στο
smd
. - Απάντηση της Apple: Η Apple επιδιόρθωσε το ζήτημα στο
smd
αντικαθιστώντας τοxpc_connection_get_audit_token
μεxpc_dictionary_get_audit_token
. - Φύση της Διόρθωσης: Η
xpc_dictionary_get_audit_token
θεωρείται ασφαλής καθώς ανακτά το audit token απευθείας από το mach message που σχετίζεται με το ληφθέν XPC μήνυμα. Ωστόσο, δεν αποτελεί μέρος του δημόσιου API, παρόμοια με τοxpc_connection_get_audit_token
. - Έλλειψη Ευρύτερης Διόρθωσης: Δεν είναι σαφές γιατί η Apple δεν εφάρμοσε μια πιο γενική διόρθωση, όπως η απόρριψη μηνυμάτων που δεν συμφωνούν με το αποθηκευμένο audit token της σύνδεσης. Η πιθανότητα νόμιμων αλλαγών audit token σε ορισμένα σενάρια (π.χ. χρήση
setuid
) μπορεί να αποτελεί παράγοντα. - Τρέχουσα Κατάσταση: Το πρόβλημα εξακολουθεί να υπάρχει σε iOS 17 και macOS 14, καθιστώντας δύσκολο για όσους προσπαθούν να το εντοπίσουν και να το κατανοήσουν.
Finding vulnerable code paths in practice (2024–2025)
Κατά τον έλεγχο υπηρεσιών XPC για αυτή την κατηγορία bug, επικεντρωθείτε σε εξουσιοδοτήσεις που εκτελούνται εκτός του event handler του μηνύματος ή ταυτόχρονα με την επεξεργασία replies.
Στατικά hints για τριάζ:
- Αναζητήστε κλήσεις σε
xpc_connection_get_audit_token
που είναι προσβάσιμες από blocks που τοποθετούνται μέσωdispatch_async
/dispatch_after
ή άλλων worker queues που τρέχουν εκτός του message handler. - Ψάξτε για helpers εξουσιοδότησης που αναμειγνύουν per-connection και per-message κατάσταση (π.χ., παίρνουν PID από
xpc_connection_get_pid
αλλά audit token απόxpc_connection_get_audit_token
). - Σε NSXPC κώδικα, επαληθεύστε ότι οι έλεγχοι γίνονται σε
-listener:shouldAcceptNewConnection:
ή, για per-message checks, ότι η υλοποίηση χρησιμοποιεί ένα per-message audit token (π.χ., το λεξικό του μηνύματος μέσωxpc_dictionary_get_audit_token
σε χαμηλότερου επιπέδου κώδικα).
Δυναμικά tips για τριάζ:
- Κάντε hook σε
xpc_connection_get_audit_token
και σημαδέψτε κλήσεις των οποίων το user stack δεν περιλαμβάνει το event-delivery path (π.χ.,_xpc_connection_mach_event
). Παράδειγμα 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);
}
}
});
Σημειώσεις:
- Στο macOS, η instrumenting προστατευμένων/Apple binaries μπορεί να απαιτεί το SIP να είναι απενεργοποιημένο ή ένα development environment· προτιμήστε να δοκιμάζετε τα δικά σας builds ή userland services.
- Για reply-forwarding races (Variant 2), παρακολουθήστε το ταυτόχρονο parsing των reply packets με fuzzing των timings του
xpc_connection_send_message_with_reply
έναντι κανονικών requests και ελέγξτε αν το effective audit token που χρησιμοποιείται κατά την authorization μπορεί να επηρεαστεί.
Exploitation primitives που πιθανότατα θα χρειαστείτε
- Multi-sender setup (Variant 1): δημιουργήστε συνδέσεις προς A και B; αντιγράψτε το send right της client port του A και χρησιμοποιήστε το ως client port του B ώστε οι απαντήσεις του B να παραδίδονται στον 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): καταλάβετε το send-once right από το pending request του A (reply port), στη συνέχεια στείλτε ένα crafted message προς το B χρησιμοποιώντας εκείνο το reply port ώστε η απάντηση του B να καταλήξει στον A ενώ το privileged request σας επεξεργάζεται.
These require low-level mach message crafting for the XPC bootstrap and message formats; review the mach/XPC primer pages in this section for the exact packet layouts and flags.
Χρήσιμα εργαλεία
- XPC sniffing/dynamic inspection: gxpc (open-source XPC sniffer) μπορεί να βοηθήσει στην καταγραφή συνδέσεων και στην παρατήρηση traffic για να επικυρώσετε multi-sender setups και timing. Example:
gxpc -p <PID> --whitelist <service-name>
. - Classic dyld interposing for libxpc: interpose on
xpc_connection_send_message*
andxpc_connection_get_audit_token
για να καταγράψετε call sites και stacks κατά τη διάρκεια black-box testing.
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
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.