Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

FluxContactConfidentialité© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-43783 — Preuve de concept et analyse technique pour CVE-2026-43783, une élévation de privilèges locale sur macOS via DesktopServicesHelper XPC permettant un chown arbitraire pour obtenir les droits root. | Kitploit
Outils/GitHubGitHub/andrd3v/cve-2026-43783
Escalade de PrivilègesAnalyse des VulnérabilitésExploitationRétro-ingénierieTests d'IntrusionAnalyse de BinairesArticles et Recherche
GitHubandrd3v/cve-2026-43783

CVE-2026-43783

Preuve de concept et analyse technique pour CVE-2026-43783, une élévation de privilèges locale sur macOS via DesktopServicesHelper XPC permettant un chown arbitraire pour obtenir les droits root.

Voir le dépôt
21427il y a 1 moisVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2026-43783 : Réparation des permissions - Obtention de root : LPE via DesktopServicesHelper dans macOS 26.5

Publié à l'origine sur PT SWARM ou andrd3v.github.io

Le démon que Finder utilise pour « réparer » les permissions sur les fichiers iCloud s'est avéré prêt à réparer les permissions sur n'importe quoi - y compris les répertoires système. Dans cet article, nous allons examiner le fonctionnement interne de DesktopServicesHelper et pourquoi une seule requête XPC a suffi pour obtenir root.

À l'intérieur de DesktopServicesHelper

Je cherchais des cibles avec com.apple.private.tcc.allow ayant la valeur kTCCServiceSystemPolicyAllFiles et DesktopServicesHelper a retenu mon attention. DesktopServicesHelper se trouve à l'emplacement /System/Library/PrivateFrameworks/DesktopServicesPriv.framework/Versions/A/Resources/DesktopServicesHelper, et Finder l'utilise pour les opérations sur les fichiers qui nécessitent des privilèges élevés : déplacer des fichiers, définir des permissions, manipuler la Corbeille.

Entitlements DesktopServicesHelper

J'ai chargé le binaire dans IDA et je me suis rendu dans start(). Après la configuration habituelle des timers et des files d'attente, il crée un listener XPC - le point d'entrée du démon. Le listener enregistre un service mach sous un nom spécifique et commence à écouter les connexions entrantes. Tout processus qui connaît ce nom peut se connecter et envoyer une requête. Voici la partie essentielle :

// get the service name
v16 = (const char *)sub_1000709F4(a1: 0);

// register the listener
mach_service = xpc_connection_create_mach_service(name: v16, targetq: nullptr, flags: 1u);

// set the incoming event handler
xpc_connection_set_event_handler(connection: mach_service, handler: &stru_1000B4B48);
xpc_connection_resume(connection: mach_service);

// start the event loop
CFRunLoopRun();

La fonction sub_1000709F4 renvoie le nom du service mach. Dans start(), elle est appelée avec l'argument 0, ce qui signifie que le démon s'enregistre sous le nom com.apple.DesktopServicesHelper.

const char *__fastcall sub_1000709F4(int a1)
{
  if ( a1 != 0 )
    return "com.apple.DesktopServicesScriptingHelper";
  else
    return "com.apple.DesktopServicesHelper";
}

stru_1000B4B48 est un bloc gestionnaire (callback) que le démon invoque pour chaque événement entrant. XPC est basé sur les messages : le client construit un dictionnaire avec des clés et des valeurs, l'envoie au démon, et le démon analyse le contenu et décide quoi faire. Tous les événements entrants aboutissent dans ce gestionnaire. Regardons à l'intérieur.

stru_1000B4B48 dans IDA

La fonction d'invocation du bloc est sub_100032044. Lors d'une nouvelle connexion, le démon récupère d'abord l'euid et l'egid du client - l'ID utilisateur effectif et l'ID de groupe - les identifiants de l'utilisateur et du groupe sous lesquels s'exécute le processus qui se connecte :

euid = xpc_connection_get_euid(connection: v8);
egid = xpc_connection_get_egid(connection: v8);
sub_100071268(a1: euid, a2: egid);

Puis il assigne un gestionnaire pour les messages entrants sur la connexion :

v15[2] = sub_10003AB2C;  // block's invoke function
xpc_connection_set_event_handler(connection: v14, handler: v15);
xpc_connection_resume(connection: v14);

sub_10003AB2C - c'est ici que les requêtes XPC réelles du client arrivent. Nous devons maintenant comprendre comment le démon décide quelles requêtes exécuter et lesquelles rejeter.

Répartiteur de requêtes

sub_10003AB2C est le répartiteur principal. C'est ici que le démon décide quoi faire d'une requête. La fonction est volumineuse, décomposons-la.

D'abord, elle extrait la chaîne "request" du message - le nom de la commande que le client souhaite exécuter :

reply = xpc_dictionary_create_reply(original: v12);
string = xpc_dictionary_get_string(xdict: v12, key: "request");
// ...
// logging: "Got Request '%{public}@'"

Ensuite, le démon récupère le jeton d'audit du processus qui se connecte et vérifie s'il s'exécute à l'intérieur d'App Sandbox. App Sandbox est un mécanisme d'isolation des applications macOS qui restreint l'accès au système de fichiers, au réseau et à d'autres ressources. C'est ici qu'il se ramifie :

xpc_dictionary_get_audit_token(a1: v12, a2: buf);
qmemcpy(__p, buf, sizeof(__p));
if ( (unsigned int)sandbox_check_by_audit_token(a1: __p, a2: 0, a3: 0) != 0 )
{
  // client is sandboxed - check against allowlist
  if ( (sub_10003B25C(a1: &v32, a2: "Handshake") & 1) == 0
    && (sub_10003B25C(a1: &v32, a2: "exit") & 1) == 0
    && (sub_10003B25C(a1: &v32, a2: "SetDefaultPermissionOnHomeSubdirectories") & 1) == 0
    && (sub_10003B25C(a1: &v32, a2: "MoveAsideICloudToArchiveInHome") & 1) == 0
    && (sub_10003B25C(a1: &v32, a2: "RepairPermissionsForCloudItems") & 1) == 0
    && (sub_10003B25C(a1: &v32, a2: "CopyClientActive") & 1) == 0
    && (sub_10003B25C(a1: &v32, a2: "DeleteItem") & 1) == 0 )
  {
    sub_100034250(a1: v12, a2: &v32); // not in the list - kill the daemon
  }
}
else
{
  // client is not sandboxed - check entitlement
  *(_QWORD *)buf = sub_1000343C0(a1: v12, a2: CFSTR("com.apple.private.tcc.allow"));
  v19 = (const __CFArray *)sub_10003B1E0();
  v20 = v19;
  if ( v19 == nullptr
    || (v35.length = CFArrayGetCount(theArray: v19),
        v35.location = 0,
        CFArrayContainsValue(theArray: v20, range: v35, value: CFSTR("kTCCServiceSystemPolicyAllFiles")) == 0) )
  {
    sub_100034250(a1: v12, a2: &v32); // no entitlement - kill the daemon
  }
}

Si le client est sandboxé - le nom de la requête est vérifié par rapport à une liste d'autorisation de sept chaînes. S'il correspond - la vérification passe et la requête est transmise. Sinon - sub_100034250 tue le démon. Si le client n'est pas sandboxé - le démon vérifie la présence de l'entitlement com.apple.private.tcc.allow avec la valeur kTCCServiceSystemPolicyAllFiles. L'absence d'entitlement signifie également la mort.

Après avoir passé la vérification, la requête traverse deux tables de gestionnaires. D'abord sub_10002F7C8, puis sub_10002A194 :

// first table (8 commands, two arguments)
v21 = sub_10002F7C8(a1: buf);
// ...
if ( v21 != 0 )
  v22(a1: v12, a2: v11); // found - invoke

// second table (21 commands, three arguments)
v27 = sub_10002A194(a1: buf);
// ...
if ( v27 != nullptr )
  v27(a1: v12, a2: reply, a3: v11); // found - invoke

Examinons maintenant les tables de gestionnaires. La première table (sub_10002F7C8) :

__int64 __fastcall sub_10002F7C8(__int64 a1)
{
  __int64 result; // x0
  void **v3; // x21
  void **v4; // x8
  _BYTE v5[32]; // [xsp+8h] [xbp-128h] BYREF
  __int64 v6; // [xsp+28h] [xbp-108h] BYREF
  __int64 v7; // [xsp+48h] [xbp-E8h] BYREF
  __int64 v8; // [xsp+68h] [xbp-C8h] BYREF
  __int64 v9; // [xsp+88h] [xbp-A8h] BYREF
  __int64 v10; // [xsp+A8h] [xbp-88h] BYREF
  __int64 v11; // [xsp+C8h] [xbp-68h] BYREF
  __int64 v12; // [xsp+E8h] [xbp-48h] BYREF
  __int64 v13; // [xsp+108h] [xbp-28h] BYREF
Télécharger l’outil