macOS xpc_connection_get_audit_token Attack
Pour plus d'informations, consultez l'article original : https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/. Voici un résumé :
Informations de base sur les messages Mach
Si vous ne savez pas ce que sont les messages Mach, commencez par consulter cette page :
Pour l'instant, retenez que (définition à partir d'ici) : Les messages Mach sont envoyés sur un port Mach, qui est un canal de communication à un seul destinataire, plusieurs expéditeurs intégré dans le noyau Mach. Plusieurs processus peuvent envoyer des messages à un port Mach, mais à tout moment, un seul processus peut les lire. Tout comme les descripteurs de fichiers et les sockets, les ports Mach sont alloués et gérés par le noyau et les processus ne voient qu'un entier, qu'ils peuvent utiliser pour indiquer au noyau lequel de leurs ports Mach ils veulent utiliser.
Connexion XPC
Si vous ne savez pas comment une connexion XPC est établie, consultez :
Résumé de la vulnérabilité
Ce qui est intéressant à savoir, c'est que l'abstraction XPC est une connexion un à un, mais elle est basée sur une technologie qui peut avoir plusieurs expéditeurs, donc :
Les ports Mach sont à un seul destinataire, plusieurs expéditeurs.
Le jeton d'audit d'une connexion XPC est le jeton d'audit copié du message le plus récemment reçu.
Obtenir le jeton d'audit d'une connexion XPC est crucial pour de nombreux contrôles de sécurité.
Bien que la situation précédente semble prometteuse, il existe des scénarios où cela ne posera pas de problèmes (à partir d'ici) :
Les jetons d'audit sont souvent utilisés pour une vérification d'autorisation afin de décider d'accepter une connexion. Comme cela se fait en utilisant un message vers le port de service, il n'y a pas encore de connexion établie. Les messages supplémentaires sur ce port seront simplement traités comme des demandes de connexion supplémentaires. Ainsi, les vérifications avant d'accepter une connexion ne sont pas vulnérables (cela signifie également que dans
-listener:shouldAcceptNewConnection:
, le jeton d'audit est sécurisé). Nous recherchons donc des connexions XPC qui vérifient des actions spécifiques.Les gestionnaires d'événements XPC sont traités de manière synchrone. Cela signifie que le gestionnaire d'événements pour un message doit être terminé avant de l'appeler pour le suivant, même sur des files d'attente de répartition concurrentes. Ainsi, à l'intérieur d'un gestionnaire d'événements XPC, le jeton d'audit ne peut pas être écrasé par d'autres messages normaux (non de réponse !).
Deux méthodes différentes par lesquelles cela pourrait être exploité :
Variante 1 :
L'exploit se connecte au service A et au service B.
Le service B peut appeler une fonctionnalité privilégiée dans le service A que l'utilisateur ne peut pas.
Le service A appelle
xpc_connection_get_audit_token
tout en n'étant pas à l'intérieur du gestionnaire d'événements pour une connexion dans undispatch_async
.Ainsi, un message différent pourrait écraser le jeton d'audit car il est envoyé de manière asynchrone en dehors du gestionnaire d'événements.
L'exploit transmet à service B le droit d'ENVOI à service A.
Ainsi, svc B enverra effectivement les messages au service A.
L'exploit tente d'appeler l'action privilégiée. Dans un RC, svc A vérifie l'autorisation de cette action tandis que svc B a écrasé le jeton d'audit (donnant à l'exploit l'accès pour appeler l'action privilégiée).
Variante 2 :
Le service B peut appeler une fonctionnalité privilégiée dans le service A que l'utilisateur ne peut pas.
L'exploit se connecte avec le service A qui lui envoie un message attendant une réponse dans un port de réponse spécifique.
L'exploit envoie au service B un message passant ce port de réponse.
Lorsque le service B répond, il envoie le message au service A, tandis que l'exploit envoie un message différent au service A essayant d'atteindre une fonctionnalité privilégiée et s'attendant à ce que la réponse de service B écrase le jeton d'audit au moment parfait (Condition de Course).
Variante 1 : appel de xpc_connection_get_audit_token en dehors d'un gestionnaire d'événements
Scénario :
Deux services Mach
A
etB
auxquels nous pouvons tous deux nous connecter (en fonction du profil de bac à sable et des vérifications d'autorisation avant d'accepter la connexion).A doit avoir une vérification d'autorisation pour une action spécifique que
B
peut passer (mais notre application ne peut pas).Par exemple, si B a des privilèges ou s'exécute en tant que root, il pourrait lui permettre de demander à A d'effectuer une action privilégiée.
Pour cette vérification d'autorisation,
A
obtient le jeton d'audit de manière asynchrone, par exemple en appelantxpc_connection_get_audit_token
depuisdispatch_async
.
Dans ce cas, un attaquant pourrait déclencher une Condition de Course en créant un exploit qui demande à A d'effectuer une action plusieurs fois tout en faisant envoyer des messages à A
par B. Lorsque la CC est réussie, le jeton d'audit de B sera copié en mémoire pendant que la demande de notre exploit est en cours de traitement par A, lui donnant accès à l'action privilégiée que seul B pourrait demander.
Cela s'est produit avec A
en tant que smd
et B
en tant que diagnosticd
. La fonction SMJobBless
de smb peut être utilisée pour installer un nouvel outil d'aide privilégié (en tant que root). Si un processus s'exécutant en tant que root contacte smd, aucune autre vérification ne sera effectuée.
Par conséquent, le service B est diagnosticd
car il s'exécute en tant que root et peut être utilisé pour surveiller un processus, donc une fois la surveillance commencée, il envoie plusieurs messages par seconde.
Pour effectuer l'attaque :
Initier une connexion au service nommé
smd
en utilisant le protocole XPC standard.Former une connexion secondaire à
diagnosticd
. Contrairement à la procédure normale, au lieu de créer et d'envoyer deux nouveaux ports Mach, le droit d'envoi du port client est remplacé par une copie du droit d'envoi associé à la connexionsmd
.En conséquence, les messages XPC peuvent être envoyés à
diagnosticd
, mais les réponses dediagnosticd
sont redirigées verssmd
. Poursmd
, il semble que les messages de l'utilisateur et dediagnosticd
proviennent de la même connexion.
Variante 2 : transfert de réponse
Dans un environnement XPC (Communication inter-processus), bien que les gestionnaires d'événements n'exécutent pas de manière concurrente, le traitement des messages de réponse a un comportement unique. Deux méthodes distinctes existent pour envoyer des messages qui attendent une réponse :
xpc_connection_send_message_with_reply
: Ici, le message XPC est reçu et traité sur une file d'attente désignée.xpc_connection_send_message_with_reply_sync
: Au contraire, dans cette méthode, le message XPC est reçu et traité sur la file d'attente de dispatch actuelle.
Cette distinction est cruciale car elle permet la possibilité de parser les paquets de réponse de manière concurrente avec l'exécution d'un gestionnaire d'événements XPC. Notamment, bien que _xpc_connection_set_creds
implémente un verrouillage pour protéger contre l'écrasement partiel du jeton d'audit, cette protection n'est pas étendue à l'objet de connexion entier. Par conséquent, cela crée une vulnérabilité où le jeton d'audit peut être remplacé pendant l'intervalle entre l'analyse d'un paquet et l'exécution de son gestionnaire d'événements.
Pour exploiter cette vulnérabilité, la configuration suivante est requise :
Deux services mach, appelés
A
etB
, qui peuvent tous deux établir une connexion.Le service
A
devrait inclure une vérification d'autorisation pour une action spécifique que seulB
peut effectuer (l'application de l'utilisateur ne peut pas).Le service
A
devrait envoyer un message qui attend une réponse.L'utilisateur peut envoyer un message à
B
auquel il répondra.
Le processus d'exploitation implique les étapes suivantes :
Attendre que le service
A
envoie un message qui attend une réponse.Au lieu de répondre directement à
A
, le port de réponse est détourné et utilisé pour envoyer un message au serviceB
.Ensuite, un message impliquant l'action interdite est envoyé, en s'attendant à ce qu'il soit traité de manière concurrente avec la réponse de
B
.
Ci-dessous se trouve une représentation visuelle du scénario d'attaque décrit :
![https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/variant2.png](../../../../../../.gitbook/assets/image (1) (1) (1) (1) (1) (1) (1).png)
Problèmes de découverte
Difficultés pour Localiser les Instances : La recherche des instances d'utilisation de
xpc_connection_get_audit_token
était difficile, à la fois statiquement et dynamiquement.Méthodologie : Frida a été utilisé pour accrocher la fonction
xpc_connection_get_audit_token
, filtrant les appels ne provenant pas des gestionnaires d'événements. Cependant, cette méthode était limitée au processus accroché et nécessitait une utilisation active.Outils d'Analyse : Des outils comme IDA/Ghidra ont été utilisés pour examiner les services mach accessibles, mais le processus était long et compliqué par des appels impliquant le cache partagé dyld.
Limitations de Scripting : Les tentatives de scripter l'analyse des appels à
xpc_connection_get_audit_token
à partir de blocsdispatch_async
ont été entravées par des complexités dans l'analyse des blocs et les interactions avec le cache partagé dyld.
La correction
Problèmes Signalés : Un rapport a été soumis à Apple détaillant les problèmes généraux et spécifiques trouvés dans
smd
.Réponse d'Apple : Apple a résolu le problème dans
smd
en remplaçantxpc_connection_get_audit_token
parxpc_dictionary_get_audit_token
.Nature de la Correction : La fonction
xpc_dictionary_get_audit_token
est considérée comme sécurisée car elle récupère le jeton d'audit directement à partir du message mach lié au message XPC reçu. Cependant, elle ne fait pas partie de l'API publique, tout commexpc_connection_get_audit_token
.Absence d'une Correction Plus Large : Il n'est pas clair pourquoi Apple n'a pas mis en place une correction plus complète, comme le rejet des messages ne correspondant pas au jeton d'audit enregistré de la connexion. La possibilité de changements légitimes du jeton d'audit dans certains scénarios (par exemple, l'utilisation de
setuid
) pourrait être un facteur.État Actuel : Le problème persiste dans iOS 17 et macOS 14, posant un défi pour ceux cherchant à l'identifier et à le comprendre.
Last updated