20 KiB
macOS XPC
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- Você trabalha em uma empresa de cibersegurança? Você quer ver sua empresa anunciada no HackTricks? ou você quer ter acesso à última versão do PEASS ou baixar o HackTricks em PDF? Verifique os PLANOS DE ASSINATURA!
- Descubra A Família PEASS, nossa coleção exclusiva de NFTs
- Adquira o swag oficial do PEASS & HackTricks
- Junte-se ao 💬 grupo Discord ou ao grupo telegram ou siga-me no Twitter 🐦@carlospolopm.
- Compartilhe seus truques de hacking enviando PRs para o repositório hacktricks e repositório hacktricks-cloud.
Informações básicas
XPC, que significa Comunicação Interprocessos (IPC) do XNU (o kernel usado pelo macOS), é uma estrutura para comunicação entre processos no macOS e iOS. O XPC fornece um mecanismo para fazer chamadas de método seguras e assíncronas entre diferentes processos no sistema. É parte do paradigma de segurança da Apple, permitindo a criação de aplicativos com privilégios separados, onde cada componente é executado com apenas as permissões necessárias para realizar seu trabalho, limitando assim os danos potenciais de um processo comprometido.
O XPC usa uma forma de Comunicação Interprocessos (IPC), que é um conjunto de métodos para que diferentes programas em execução no mesmo sistema enviem dados de ida e volta.
Os principais benefícios do XPC incluem:
- Segurança: Ao separar o trabalho em diferentes processos, cada processo pode receber apenas as permissões necessárias. Isso significa que, mesmo que um processo seja comprometido, ele tem capacidade limitada de causar danos.
- Estabilidade: O XPC ajuda a isolar falhas no componente onde ocorrem. Se um processo falhar, ele pode ser reiniciado sem afetar o restante do sistema.
- Desempenho: O XPC permite fácil concorrência, pois diferentes tarefas podem ser executadas simultaneamente em diferentes processos.
A única desvantagem é que separar um aplicativo em vários processos que se comunicam via XPC é menos eficiente. Mas nos sistemas de hoje isso quase não é perceptível e os benefícios são maiores.
Serviços XPC específicos do aplicativo
Os componentes XPC de um aplicativo estão dentro do próprio aplicativo. Por exemplo, no Safari, você pode encontrá-los em /Applications/Safari.app/Contents/XPCServices
. Eles têm a extensão .xpc
(como com.apple.Safari.SandboxBroker.xpc
) e também são bundles com o binário principal dentro dele: /Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/MacOS/com.apple.Safari.SandboxBroker
e um Info.plist: /Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/Info.plist
Como você pode estar pensando, um componente XPC terá diferentes direitos e privilégios do que os outros componentes XPC ou o binário principal do aplicativo. EXCETO se um serviço XPC for configurado com JoinExistingSession definido como "True" em seu arquivo Info.plist. Nesse caso, o serviço XPC será executado na mesma sessão de segurança do aplicativo que o chamou.
Os serviços XPC são iniciados pelo launchd quando necessário e encerrados quando todas as tarefas são concluídas para liberar recursos do sistema. Os componentes XPC específicos do aplicativo só podem ser utilizados pelo aplicativo, reduzindo assim o risco associado a possíveis vulnerabilidades.
Serviços XPC em todo o sistema
Os serviços XPC em todo o sistema são acessíveis a todos os usuários. Esses serviços, sejam do tipo launchd ou Mach, precisam ser definidos em arquivos plist localizados em diretórios especificados, como /System/Library/LaunchDaemons
, /Library/LaunchDaemons
, /System/Library/LaunchAgents
ou /Library/LaunchAgents
.
Esses arquivos plist terão uma chave chamada MachServices
com o nome do serviço e uma chave chamada Program
com o caminho para o binário:
cat /Library/LaunchDaemons/com.jamf.management.daemon.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Program</key>
<string>/Library/Application Support/JAMF/Jamf.app/Contents/MacOS/JamfDaemon.app/Contents/MacOS/JamfDaemon</string>
<key>AbandonProcessGroup</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>com.jamf.management.daemon</string>
<key>MachServices</key>
<dict>
<key>com.jamf.management.daemon.aad</key>
<true/>
<key>com.jamf.management.daemon.agent</key>
<true/>
<key>com.jamf.management.daemon.binary</key>
<true/>
<key>com.jamf.management.daemon.selfservice</key>
<true/>
<key>com.jamf.management.daemon.service</key>
<true/>
</dict>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
Os presentes em LaunchDameons
são executados pelo root. Portanto, se um processo não privilegiado puder se comunicar com um deles, poderá ser capaz de elevar os privilégios.
Mensagens de Evento XPC
As aplicações podem se inscrever em diferentes mensagens de evento, permitindo que sejam iniciadas sob demanda quando esses eventos ocorrerem. A configuração desses serviços é feita em arquivos plist do launchd, localizados nos mesmos diretórios dos anteriores e contendo uma chave extra LaunchEvent
.
Verificação do Processo Conectado XPC
Quando um processo tenta chamar um método por meio de uma conexão XPC, o serviço XPC deve verificar se esse processo tem permissão para se conectar. Aqui estão as maneiras comuns de verificar isso e as armadilhas comuns:
{% content-ref url="macos-xpc-connecting-process-check.md" %} macos-xpc-connecting-process-check.md {% endcontent-ref %}
Autorização XPC
A Apple também permite que os aplicativos configurem alguns direitos e como obtê-los, para que, se o processo de chamada os tiver, seja permitido chamar um método do serviço XPC:
{% content-ref url="macos-xpc-authorization.md" %} macos-xpc-authorization.md {% endcontent-ref %}
Sniffer XPC
Para interceptar as mensagens XPC, você pode usar o xpcspy, que utiliza o Frida.
# Install
pip3 install xpcspy
pip3 install xpcspy --no-deps # To not make xpcspy install Frida 15 and downgrade your Frida installation
# Start sniffing
xpcspy -U -r -W <bundle-id>
## Using filters (i: for input, o: for output)
xpcspy -U <prog-name> -t 'i:com.apple.*' -t 'o:com.apple.*' -r
Exemplo de Código em C
{% tabs %} {% tab title="xpc_server.c" %}
// gcc xpc_server.c -o xpc_server
#include <xpc/xpc.h>
static void handle_event(xpc_object_t event) {
if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) {
// Print received message
const char* received_message = xpc_dictionary_get_string(event, "message");
printf("Received message: %s\n", received_message);
// Create a response dictionary
xpc_object_t response = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_string(response, "received", "received");
// Send response
xpc_connection_t remote = xpc_dictionary_get_remote_connection(event);
xpc_connection_send_message(remote, response);
// Clean up
xpc_release(response);
}
}
static void handle_connection(xpc_connection_t connection) {
xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
handle_event(event);
});
xpc_connection_resume(connection);
}
int main(int argc, const char *argv[]) {
xpc_connection_t service = xpc_connection_create_mach_service("xyz.hacktricks.service",
dispatch_get_main_queue(),
XPC_CONNECTION_MACH_SERVICE_LISTENER);
if (!service) {
fprintf(stderr, "Failed to create service.\n");
exit(EXIT_FAILURE);
}
xpc_connection_set_event_handler(service, ^(xpc_object_t event) {
xpc_type_t type = xpc_get_type(event);
if (type == XPC_TYPE_CONNECTION) {
handle_connection(event);
}
});
xpc_connection_resume(service);
dispatch_main();
return 0;
}
{% tab title="xpc_client.c" %}
#include <stdio.h>
#include <stdlib.h>
#include <xpc/xpc.h>
int main(int argc, const char * argv[]) {
xpc_connection_t connection = xpc_connection_create_mach_service("com.apple.securityd", NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
xpc_type_t type = xpc_get_type(event);
if (type == XPC_TYPE_DICTIONARY) {
const char *description = xpc_dictionary_get_string(event, "description");
printf("Received event: %s\n", description);
}
});
xpc_connection_resume(connection);
dispatch_main();
return 0;
}
{% endtab %}
{% tab title="xpc_server.c" %}
// gcc xpc_client.c -o xpc_client
#include <xpc/xpc.h>
int main(int argc, const char *argv[]) {
xpc_connection_t connection = xpc_connection_create_mach_service("xyz.hacktricks.service", NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) {
// Print received message
const char* received_message = xpc_dictionary_get_string(event, "received");
printf("Received message: %s\n", received_message);
}
});
xpc_connection_resume(connection);
xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_string(message, "message", "Hello, Server!");
xpc_connection_send_message(connection, message);
dispatch_main();
return 0;
}
{% tab title="xyz.hacktricks.service.plist" %}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0">
<dict>
<key>Label</key>
<string>xyz.hacktricks.service</string>
<key>MachServices</key>
<dict>
<key>xyz.hacktricks.service</key>
<true/>
</dict>
<key>Program</key>
<string>/tmp/xpc_server</string>
<key>ProgramArguments</key>
<array>
<string>/tmp/xpc_server</string>
</array>
</dict>
</plist>
{% endtab %} {% endtabs %}
# Compile the server & client
gcc xpc_server.c -o xpc_server
gcc xpc_client.c -o xpc_client
# Save server on it's location
cp xpc_server /tmp
# Load daemon
sudo cp xyz.hacktricks.service.plist /Library/LaunchDaemons
sudo launchctl load /Library/LaunchDaemons/xyz.hacktricks.service.plist
# Call client
./xpc_client
# Clean
sudo launchctl unload /Library/LaunchDaemons/xyz.hacktricks.service.plist
sudo rm /Library/LaunchDaemons/xyz.hacktricks.service.plist /tmp/xpc_server
Exemplo de Código Objective-C
{% tabs %} {% tab title="oc_xpc_server.m" %}
// gcc -framework Foundation oc_xpc_server.m -o oc_xpc_server
#include <Foundation/Foundation.h>
@protocol MyXPCProtocol
- (void)sayHello:(NSString *)some_string withReply:(void (^)(NSString *))reply;
@end
@interface MyXPCObject : NSObject <MyXPCProtocol>
@end
@implementation MyXPCObject
- (void)sayHello:(NSString *)some_string withReply:(void (^)(NSString *))reply {
NSLog(@"Received message: %@", some_string);
NSString *response = @"Received";
reply(response);
}
@end
@interface MyDelegate : NSObject <NSXPCListenerDelegate>
@end
@implementation MyDelegate
- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection {
newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MyXPCProtocol)];
MyXPCObject *my_object = [MyXPCObject new];
newConnection.exportedObject = my_object;
[newConnection resume];
return YES;
}
@end
int main(void) {
NSXPCListener *listener = [[NSXPCListener alloc] initWithMachServiceName:@"xyz.hacktricks.svcoc"];
id <NSXPCListenerDelegate> delegate = [MyDelegate new];
listener.delegate = delegate;
[listener resume];
sleep(10); // Fake something is done and then it ends
}
{% tab title="oc_xpc_client.m" %}
// gcc -framework Foundation oc_xpc_client.m -o oc_xpc_client
#include <Foundation/Foundation.h>
@protocol MyXPCProtocol
- (void)sayHello:(NSString *)some_string withReply:(void (^)(NSString *))reply;
@end
int main(void) {
NSXPCConnection *connection = [[NSXPCConnection alloc] initWithMachServiceName:@"xyz.hacktricks.svcoc" options:NSXPCConnectionPrivileged];
connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MyXPCProtocol)];
[connection resume];
[[connection remoteObjectProxy] sayHello:@"Hello, Server!" withReply:^(NSString *response) {
NSLog(@"Received response: %@", response);
}];
[[NSRunLoop currentRunLoop] run];
return 0;
}
{% tab title="xyz.hacktricks.svcoc.plist" %}
O arquivo xyz.hacktricks.svcoc.plist
é um arquivo de propriedades do Launchd usado para definir e controlar serviços no macOS. O Launchd é o sistema de inicialização e gerenciamento de processos do macOS. O arquivo plist contém informações sobre o serviço, como o caminho do executável, argumentos, variáveis de ambiente e outras configurações.
Para explorar vulnerabilidades de escalonamento de privilégios usando o arquivo xyz.hacktricks.svcoc.plist
, você pode procurar por configurações inadequadas que permitam a execução de comandos privilegiados ou a substituição do executável por um binário malicioso. Além disso, você pode verificar se há permissões excessivas definidas para o arquivo plist, o que pode permitir a modificação não autorizada.
É importante ressaltar que a exploração de vulnerabilidades de escalonamento de privilégios é ilegal e deve ser realizada apenas em um ambiente controlado e com permissão adequada.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0">
<dict>
<key>Label</key>
<string>xyz.hacktricks.svcoc</string>
<key>MachServices</key>
<dict>
<key>xyz.hacktricks.svcoc</key>
<true/>
</dict>
<key>Program</key>
<string>/tmp/oc_xpc_server</string>
<key>ProgramArguments</key>
<array>
<string>/tmp/oc_xpc_server</string>
</array>
</dict>
</plist>
{% endtab %} {% endtabs %}
# Compile the server & client
gcc -framework Foundation oc_xpc_server.m -o oc_xpc_server
gcc -framework Foundation oc_xpc_client.m -o oc_xpc_client
# Save server on it's location
cp oc_xpc_server /tmp
# Load daemon
sudo cp xyz.hacktricks.svcoc.plist /Library/LaunchDaemons
sudo launchctl load /Library/LaunchDaemons/xyz.hacktricks.svcoc.plist
# Call client
./oc_xpc_client
# Clean
sudo launchctl unload /Library/LaunchDaemons/xyz.hacktricks.svcoc.plist
sudo rm /Library/LaunchDaemons/xyz.hacktricks.svcoc.plist /tmp/oc_xpc_server
Cliente dentro de um código Dylb
O código a seguir demonstra como criar um cliente dentro de um código Dylb para se comunicar com um serviço XPC em um sistema macOS.
#include <xpc/xpc.h>
int main(int argc, const char * argv[]) {
xpc_connection_t connection = xpc_connection_create_mach_service("com.example.service", NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
// Manipule as respostas recebidas do serviço XPC aqui
});
xpc_connection_resume(connection);
xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_string(message, "key", "value");
xpc_connection_send_message_with_reply(connection, message, dispatch_get_main_queue(), ^(xpc_object_t response) {
// Manipule a resposta recebida do serviço XPC aqui
});
dispatch_main();
return 0;
}
Certifique-se de substituir "com.example.service"
pelo identificador do serviço XPC ao qual você deseja se conectar. Você também pode personalizar as manipulações de eventos e respostas de acordo com suas necessidades.
Este código cria uma conexão com o serviço XPC especificado e define manipuladores de eventos para lidar com as respostas recebidas do serviço. Em seguida, ele cria uma mensagem XPC e a envia para o serviço XPC usando a função xpc_connection_send_message_with_reply()
. Por fim, o código entra em um loop de execução principal usando dispatch_main()
para manter a conexão ativa.
Certifique-se de compilar e executar o código em um ambiente macOS adequado com as permissões necessárias para se comunicar com o serviço XPC desejado.
// gcc -dynamiclib -framework Foundation oc_xpc_client.m -o oc_xpc_client.dylib
// gcc injection example:
// DYLD_INSERT_LIBRARIES=oc_xpc_client.dylib /path/to/vuln/bin
#import <Foundation/Foundation.h>
@protocol MyXPCProtocol
- (void)sayHello:(NSString *)some_string withReply:(void (^)(NSString *))reply;
@end
__attribute__((constructor))
static void customConstructor(int argc, const char **argv)
{
NSString* _serviceName = @"xyz.hacktricks.svcoc";
NSXPCConnection* _agentConnection = [[NSXPCConnection alloc] initWithMachServiceName:_serviceName options:4096];
[_agentConnection setRemoteObjectInterface:[NSXPCInterface interfaceWithProtocol:@protocol(MyXPCProtocol)]];
[_agentConnection resume];
[[_agentConnection remoteObjectProxyWithErrorHandler:^(NSError* error) {
(void)error;
NSLog(@"Connection Failure");
}] sayHello:@"Hello, Server!" withReply:^(NSString *response) {
NSLog(@"Received response: %@", response);
} ];
NSLog(@"Done!");
return;
}
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- Você trabalha em uma empresa de cibersegurança? Você quer ver sua empresa anunciada no HackTricks? ou você quer ter acesso à última versão do PEASS ou baixar o HackTricks em PDF? Verifique os PLANOS DE ASSINATURA!
- Descubra A Família PEASS, nossa coleção exclusiva de NFTs
- Adquira o swag oficial do PEASS & HackTricks
- Junte-se ao 💬 grupo Discord ou ao grupo telegram ou siga-me no Twitter 🐦@carlospolopm.
- Compartilhe seus truques de hacking enviando PRs para o repositório hacktricks e repositório hacktricks-cloud.