.. | ||
macos-xpc-connecting-process-check | ||
macos-xpc-authorization.md | ||
macos-xpc-connecting-process-check.md | ||
README.md |
macOS XPC
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- ¿Trabajas en una empresa de ciberseguridad? ¿Quieres ver tu empresa anunciada en HackTricks? ¿O quieres tener acceso a la última versión de PEASS o descargar HackTricks en PDF? ¡Consulta los PLANES DE SUSCRIPCIÓN!
- Descubre The PEASS Family, nuestra colección exclusiva de NFTs
- Obtén el swag oficial de PEASS y HackTricks
- Únete al 💬 grupo de Discord o al grupo de Telegram o sígueme en Twitter 🐦@carlospolopm.
- Comparte tus trucos de hacking enviando PRs al repositorio de hacktricks y al repositorio de hacktricks-cloud.
Información básica
XPC, que significa Comunicación entre Procesos de XNU (el kernel utilizado por macOS), es un marco de trabajo para la comunicación entre procesos en macOS e iOS. XPC proporciona un mecanismo para realizar llamadas de método seguras y asíncronas entre diferentes procesos en el sistema. Es parte del paradigma de seguridad de Apple, que permite la creación de aplicaciones con privilegios separados donde cada componente se ejecuta con solo los permisos necesarios para realizar su trabajo, limitando así el daño potencial de un proceso comprometido.
XPC utiliza una forma de Comunicación entre Procesos (IPC), que es un conjunto de métodos para que los programas diferentes que se ejecutan en el mismo sistema envíen datos de ida y vuelta.
Los principales beneficios de XPC incluyen:
- Seguridad: Al separar el trabajo en diferentes procesos, cada proceso puede recibir solo los permisos que necesita. Esto significa que incluso si un proceso está comprometido, tiene una capacidad limitada para causar daño.
- Estabilidad: XPC ayuda a aislar los bloqueos en el componente donde ocurren. Si un proceso se bloquea, se puede reiniciar sin afectar al resto del sistema.
- Rendimiento: XPC permite una fácil concurrencia, ya que diferentes tareas se pueden ejecutar simultáneamente en diferentes procesos.
La única desventaja es que separar una aplicación en varios procesos que se comunican a través de XPC es menos eficiente. Pero en los sistemas actuales esto apenas se nota y los beneficios son mayores.
Servicios XPC específicos de la aplicación
Los componentes XPC de una aplicación están dentro de la propia aplicación. Por ejemplo, en Safari se pueden encontrar en /Applications/Safari.app/Contents/XPCServices
. Tienen la extensión .xpc
(como com.apple.Safari.SandboxBroker.xpc
) y también son paquetes con el binario principal dentro de él: /Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/MacOS/com.apple.Safari.SandboxBroker
y un Info.plist: /Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/Info.plist
Como podrás pensar, un componente XPC tendrá diferentes derechos y privilegios que los otros componentes XPC o el binario principal de la aplicación. EXCEPTO si un servicio XPC está configurado con JoinExistingSession establecido en "True" en su archivo Info.plist. En este caso, el servicio XPC se ejecutará en la misma sesión de seguridad que la aplicación que lo llamó.
Los servicios XPC se inician mediante launchd cuando es necesario y se cierran una vez que todas las tareas están completas para liberar recursos del sistema. Los componentes XPC específicos de la aplicación solo pueden ser utilizados por la aplicación, lo que reduce el riesgo asociado con posibles vulnerabilidades.
Servicios XPC de todo el sistema
Los servicios XPC de todo el sistema son accesibles para todos los usuarios. Estos servicios, ya sean de tipo launchd o Mach, deben estar definidos en archivos plist ubicados en directorios especificados como /System/Library/LaunchDaemons
, /Library/LaunchDaemons
, /System/Library/LaunchAgents
o /Library/LaunchAgents
.
Estos archivos plist tendrán una clave llamada MachServices
con el nombre del servicio y una clave llamada Program
con la ruta al binario:
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>
Los que están en LaunchDameons
son ejecutados por root. Por lo tanto, si un proceso sin privilegios puede comunicarse con uno de ellos, podría ser capaz de escalar privilegios.
Mensajes de eventos XPC
Las aplicaciones pueden suscribirse a diferentes mensajes de eventos, lo que les permite ser iniciadas a pedido cuando ocurren dichos eventos. La configuración de estos servicios se realiza en archivos plist de launchd, ubicados en los mismos directorios que los anteriores y que contienen una clave adicional LaunchEvent
.
Verificación del proceso de conexión XPC
Cuando un proceso intenta llamar a un método a través de una conexión XPC, el servicio XPC debe verificar si ese proceso tiene permitido conectarse. Aquí se muestran las formas comunes de verificar eso y las trampas comunes:
{% content-ref url="macos-xpc-connecting-process-check/" %} macos-xpc-connecting-process-check {% endcontent-ref %}
Autorización XPC
Apple también permite que las aplicaciones configuren algunos derechos y cómo obtenerlos, por lo que si el proceso que llama los tiene, se le permitiría llamar a un método del servicio XPC:
{% content-ref url="macos-xpc-authorization.md" %} macos-xpc-authorization.md {% endcontent-ref %}
Espía XPC
Para espiar los mensajes XPC, puedes usar xpcspy que utiliza 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
Ejemplo de código en 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" %}
// 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
Ejemplo 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" %}
xyz.hacktricks.svcoc.plist
Este archivo de propiedad de la lista de servicios de macOS (plist) se utiliza para definir los servicios que se ejecutan en segundo plano en un proceso separado. Los servicios se comunican entre sí utilizando el marco XPC (Interfaz de comunicación entre procesos).
Ubicación del archivo
El archivo xyz.hacktricks.svcoc.plist
se encuentra en la siguiente ubicación en macOS:
/Library/LaunchDaemons/xyz.hacktricks.svcoc.plist
Contenido del archivo
El archivo plist contiene información sobre el servicio, incluyendo su nombre, ruta de ejecución, argumentos y más. Aquí hay un ejemplo de cómo se ve el contenido del archivo:
<?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>ProgramArguments</key>
<array>
<string>/usr/bin/python</string>
<string>/path/to/script.py</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
Modificación del archivo
Para modificar el archivo xyz.hacktricks.svcoc.plist
, se puede utilizar un editor de texto o la utilidad plutil
en la línea de comandos. Asegúrese de tener privilegios de administrador para realizar cambios en el archivo.
Reinicio del servicio
Después de realizar cambios en el archivo plist, es necesario reiniciar el servicio para que los cambios surtan efecto. Esto se puede hacer utilizando el comando launchctl
en la línea de comandos:
sudo launchctl unload /Library/LaunchDaemons/xyz.hacktricks.svcoc.plist
sudo launchctl load /Library/LaunchDaemons/xyz.hacktricks.svcoc.plist
Seguridad y consideraciones
Es importante tener en cuenta que los servicios que se ejecutan en segundo plano pueden representar un riesgo de seguridad si no se configuran correctamente. Asegúrese de revisar y auditar regularmente los archivos plist para detectar posibles vulnerabilidades y abusos.
{% endtab %}
<?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 un código Dylb
The Dylb code allows the creation of a client that can communicate with a server using the XPC framework in macOS. This client code can be embedded within an application to establish inter-process communication (IPC) with the server.
To create a client inside a Dylb code, follow these steps:
- Import the necessary frameworks:
#import <Foundation/Foundation.h>
#import <xpc/xpc.h>
- Define the XPC connection and event handler:
static xpc_connection_t connection;
static dispatch_queue_t queue;
void eventHandler(xpc_object_t event) {
// Handle incoming events from the server
// ...
}
- Implement the client code:
int main(int argc, const char * argv[]) {
@autoreleasepool {
// Create the XPC connection
connection = xpc_connection_create_mach_service("com.example.server", queue, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
// Set the event handler
xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
eventHandler(event);
});
// Resume the connection
xpc_connection_resume(connection);
// Send a message to the server
xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_string(message, "key", "value");
xpc_connection_send_message(connection, message);
// Run the main loop
dispatch_main();
}
return 0;
}
- Customize the code according to your requirements, such as handling incoming events and sending messages to the server.
Remember to replace "com.example.server"
with the Mach service name of the server you want to communicate with.
By embedding this client code within your application, you can establish IPC with a server using the XPC framework in macOS.
// 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 🎥
- ¿Trabajas en una empresa de ciberseguridad? ¿Quieres ver tu empresa anunciada en HackTricks? ¿O quieres tener acceso a la última versión de PEASS o descargar HackTricks en PDF? ¡Consulta los PLANES DE SUSCRIPCIÓN!
- Descubre La Familia PEASS, nuestra colección exclusiva de NFTs
- Obtén el merchandising oficial de PEASS y HackTricks
- Únete al 💬 grupo de Discord o al grupo de Telegram o sígueme en Twitter 🐦@carlospolopm.
- Comparte tus trucos de hacking enviando PRs al repositorio de hacktricks y al repositorio de hacktricks-cloud.