Skip to content
KitploitKITPLOIT
OutilsBlog
Log in
Soumettre
OutilsBlog
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
launchd-portrep — CVE-2018-4280 : vulnérabilité de remplacement de port Mach dans launchd sur macOS 10.13.5 entraînant une élévation de privilèges locale et un contournement de SIP. | Kitploit
Outils/GitHubGitHub/bazad/launchd-portrep
Escalade de PrivilègesFrameworks d'ExploitationExploitationTests d'IntrusionRed TeamingExploitation de Binaires
GitHubbazad/launchd-portrep

launchd-portrep

CVE-2018-4280 : vulnérabilité de remplacement de port Mach dans launchd sur macOS 10.13.5 entraînant une élévation de privilèges locale et un contournement de SIP.

Voir le dépôt
59610il y a 7 ansVé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

launchd-portrep

launchd-portrep est un exploit pour une vulnérabilité de remplacement de port dans launchd, le premier processus de l'espace utilisateur et démon de gestion des services sur macOS. En envoyant un message Mach spécialement conçu au port bootstrap, launchd peut être contraint de désallouer son droit d'envoi pour tout port Mach pour lequel l'attaquant possède également un droit d'envoi. Cela permet à l'attaquant d'usurper auprès du reste du système tout service launchd qu'il peut résoudre.

La vulnérabilité

Launchd multiplexe plusieurs gestionnaires de messages Mach différents sur son port principal, y compris un gestionnaire MIG pour les messages d'exception. Si un processus envoie un message mach_exception_raise ou mach_exception_raise_state_identity à son propre port bootstrap, launchd recevra et traitera ce message comme une exception au niveau de l'hôte.

Malheureusement, la gestion de ces messages par launchd est défectueuse. Si le type d'exception est EXC_CRASH, launchd désalloue les ports thread et tâche envoyés dans le message, puis retourne KERN_FAILURE depuis la routine de service, ce qui amène le système MIG à désallouer à nouveau les ports thread et tâche. (L'hypothèse est que si une routine de service retourne un succès, elle a pris possession de toutes les ressources du message Mach, tandis que si la routine de service retourne une erreur, elle n'a pris possession d'aucune des ressources.)

Voici le code de la routine de service de launchd pour les messages mach_exception_raise, décompilé avec IDA/Hex-Rays et légèrement édité pour plus de lisibilité :

kern_return_t __fastcall
catch_mach_exception_raise(                             // (a) The service routine is
        mach_port_t           exception_port,           //     called with values directly
        mach_port_t           thread,                   //     from the Mach message
        mach_port_t           task,                     //     sent by the client. The
        unsigned int          exception,                //     thread and task ports could
        mach_exception_data_t code,                     //     be arbitrary send rights.
        unsigned int          codeCnt)
{
    kern_return_t kr;      // eax@1 MAPDST
    kern_return_t result;  // eax@10
    int pid;               // [rsp+14h] [rbp-43Ch]@1
    char codes_str[1024];  // [rsp+20h] [rbp-430h]@5
    __int64 __stack_guard; // [rsp+420h] [rbp-30h]@1

    __stack_guard = *__stack_chk_guard_ptr;
    pid = -1;
    kr = pid_for_task(task, &pid);
    if ( kr )
    {
        _os_assumes_log(kr);
        _os_avoid_tail_call();
    }
    if ( codeCnt )
    {
        do
        {
            __snprintf_chk(codes_str, 0x400uLL, 0, 0x400uLL, "0x%llx", *code);
            ++code;
            --codeCnt;
        }
        while ( codeCnt );
    }
    launchd_log_2(
        0LL,
        3LL,
        "Host-level exception raised: pid = %d, thread = 0x%x, "
            "exception type = 0x%x, codes = { %s }",
        pid,
        thread,
        exception,
        codes_str);
    kr = deallocate_mach_port(thread);                  // (b) The "thread" port sent in
    if ( kr )                                           //     the message is deallocated.
    {
        _os_assumes_log(kr);
        _os_avoid_tail_call();
    }
    kr = deallocate_mach_port(task);                    // (c) The "task" port sent in the
    if ( kr )                                           //     message is deallocated.
    {
        _os_assumes_log(kr);
        _os_avoid_tail_call();
    }
    result = 0;
    if ( *__stack_chk_guard_ptr == __stack_guard )
    {
        LOBYTE(result) = exception == 10;               // (d) If the exception type is 10
        result *= 5;                                    //     (EXC_CRASH), then an error
    }                                                   //     KERN_FAILURE is returned.
    return result;                                      //     MIG will deallocate the
}                                                       //     ports again.

Cette double désallocation des noms de ports est problématique car un processus peut définir les ports de son choix comme ports tâche et thread dans le message d'exception. Launchd ne vérifie pas que les droits d'envoi reçus correspondent réellement à un thread et à une tâche ; les ports pourraient, par exemple, être des droits d'envoi vers des ports déjà présents dans l'espace IPC de launchd. La double désallocation amènerait alors launchd à abandonner une référence utilisateur sur l'un de ses propres ports.

Ce bug peut être exploité pour libérer le droit d'envoi de launchd vers tout port Mach pour lequel le processus attaquant possède également un droit d'envoi. En particulier, si le processus attaquant peut résoudre un service système via launchd, il peut libérer le droit d'envoi de launchd vers ce service, puis usurper ce service auprès du reste du système. Ensuite, il existe de nombreuses voies différentes pour obtenir des privilèges système.

Stratégie d'exploitation pour obtenir task_for_pid-allow

Ce bug est une version moins générale de CVE-2016-7637, un problème de gestion des références utilisateur de ports Mach dans XNU découvert par Ian Beer qui permettait aux processus de libérer des ports Mach dans d'autres processus. Ian Beer a exploité cette vulnérabilité sur macOS en remplaçant le droit d'envoi de launchd vers le point de terminaison com.apple.CoreServices.coreservicesd et en se faisant passer pour coreservicesd auprès du reste du système. Coreservicesd est une cible intéressante car c'est l'un des rares services auxquels les clients envoient leur port de tâche dans un message Mach. En remplaçant le droit d'envoi de launchd vers coreservicesd par son propre port, puis en déclenchant des clients privilégiés pour résoudre et communiquer avec coreservicesd, il a pu obtenir le port de tâche d'un processus privilégié, puis exécuter du code dans ce processus.

Comme le comportement de macOS n'a pas changé, j'ai essentiellement copié la stratégie d'exploitation d'Ian Beer pour cette vulnérabilité. Nous envoyons à launchd des messages d'exception contenant le port de service de coreservicesd jusqu'à ce que nous libérions le droit d'envoi de launchd vers ce port. Nous pouvons détecter quand nous avons libéré le droit en appelant à nouveau bootstrap_look_up() sur le service : si launchd retourne un nom de port invalide, alors nous avons réussi à libérer le droit d'envoi de launchd vers le port. Ensuite, nous enregistrons et désenregistrons à plusieurs reprises un grand nombre de services auprès de launchd jusqu'à ce que l'un des services que nous enregistrons reçoive le même nom de port Mach dans l'espace IPC de launchd que le port coreservicesd d'origine. À ce stade, tout processus qui résout com.apple.CoreServices.coreservicesd dans launchd recevra un droit d'envoi vers notre faux service plutôt que vers le vrai coreservicesd. Nous exécutons alors un serveur MITM sur le port du faux service, inspectant tous les ports Mach dans les messages reçus des clients avant de les transmettre au vrai coreservicesd. À ce moment, nous envoyons un message à sysdiagnose l'amenant à exécuter un tailspin, ce qui fait que sysdiagnose se connecte à notre faux port coreservicesd et nous envoie son port de tâche. Comme sysdiagnose possède l'entitlement task_for_pid-allow, nous pouvons maintenant obtenir le port de tâche de n'importe quel processus.

Télécharger l’outil