XPC, che sta per XNU (il kernel utilizzato da macOS) Inter-Process Communication, è un framework per la comunicazione tra processi su macOS e iOS. XPC fornisce un meccanismo per effettuare chiamate di metodo sicure e asincrone tra processi diversi nel sistema. Fa parte del paradigma di sicurezza di Apple, consentendo la creazione di applicazioni con privilegi separati in cui ogni componente viene eseguito con solo i permessi necessari per svolgere il proprio lavoro, limitando così i danni potenziali da un processo compromesso.
XPC utilizza una forma di Inter-Process Communication (IPC), che è un insieme di metodi per inviare dati avanti e indietro tra programmi diversi in esecuzione sullo stesso sistema.
I principali vantaggi di XPC includono:
Sicurezza: Separando il lavoro in diversi processi, ogni processo può essere autorizzato solo ai permessi necessari. Ciò significa che anche se un processo viene compromesso, ha una capacità limitata di causare danni.
Stabilità: XPC aiuta a isolare i crash al componente in cui si verificano. Se un processo si blocca, può essere riavviato senza influire sul resto del sistema.
Prestazioni: XPC consente una facile concorrenza, poiché diverse attività possono essere eseguite contemporaneamente in diversi processi.
L'unico svantaggio è che separare un'applicazione in diversi processi che comunicano tramite XPC è meno efficiente. Ma nei sistemi odierni questo è quasi impercettibile e i vantaggi sono maggiori.
Servizi XPC specifici dell'applicazione
I componenti XPC di un'applicazione sono all'interno dell'applicazione stessa. Ad esempio, in Safari puoi trovarli in /Applications/Safari.app/Contents/XPCServices. Hanno l'estensione .xpc (come com.apple.Safari.SandboxBroker.xpc) e sono anche bundle con il binario principale al suo interno: /Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/MacOS/com.apple.Safari.SandboxBroker e un Info.plist: /Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/Info.plist
Come potresti pensare, un componente XPC avrà diversi diritti e privilegi rispetto agli altri componenti XPC o al binario principale dell'applicazione. ECCETTO se un servizio XPC è configurato con JoinExistingSession impostato su "True" nel suo file Info.plist. In questo caso, il servizio XPC verrà eseguito nella stessa sessione di sicurezza dell'applicazione che lo ha chiamato.
I servizi XPC vengono avviati da launchd quando necessario e chiusi una volta completate tutte le attività per liberare le risorse di sistema. I componenti XPC specifici dell'applicazione possono essere utilizzati solo dall'applicazione, riducendo così il rischio associato a potenziali vulnerabilità.
Servizi XPC a livello di sistema
I servizi XPC a livello di sistema sono accessibili a tutti gli utenti. Questi servizi, sia di tipo launchd che di tipo Mach, devono essere definiti in file plist situati in directory specificate come /System/Library/LaunchDaemons, /Library/LaunchDaemons, /System/Library/LaunchAgents, o /Library/LaunchAgents.
Questi file plist avranno una chiave chiamata MachServices con il nome del servizio e una chiave chiamata Program con il percorso del binario:
Quelli in LaunchDameons sono eseguiti da root. Quindi, se un processo non privilegiato può comunicare con uno di questi, potrebbe essere in grado di ottenere privilegi elevati.
Messaggi di evento XPC
Le applicazioni possono sottoscriversi a diversi messaggi di evento, consentendo loro di essere iniziate su richiesta quando tali eventi si verificano. La configurazione di questi servizi viene effettuata nei file plist di launchd, situati nelle stesse directory dei precedenti e contenenti una chiave LaunchEvent aggiuntiva.
Controllo del processo di connessione XPC
Quando un processo tenta di chiamare un metodo tramite una connessione XPC, il servizio XPC dovrebbe verificare se tale processo è autorizzato a connettersi. Ecco i modi comuni per effettuare tale verifica e le trappole comuni:
Apple consente anche alle app di configurare alcuni diritti e come ottenerli, quindi se il processo chiamante li possiede, sarà autorizzato a chiamare un metodo dal servizio XPC:
Per intercettare i messaggi XPC, è possibile utilizzare xpcspy che utilizza Frida.
# Installpip3installxpcspypip3installxpcspy--no-deps# To not make xpcspy install Frida 15 and downgrade your Frida installation# Start sniffingxpcspy-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
# Compile the server & clientgccxpc_server.c-oxpc_servergccxpc_client.c-oxpc_client# Save server on it's locationcpxpc_server/tmp# Load daemonsudocpxyz.hacktricks.service.plist/Library/LaunchDaemonssudolaunchctlload/Library/LaunchDaemons/xyz.hacktricks.service.plist# Call client./xpc_client# Cleansudolaunchctlunload/Library/LaunchDaemons/xyz.hacktricks.service.plistsudorm/Library/LaunchDaemons/xyz.hacktricks.service.plist/tmp/xpc_server
```bash # 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
## Client all'interno di un codice Dylb
The client code is responsible for establishing a connection with the server and sending requests to it. In the case of a Dylb code, the client is embedded within the code itself.
Il codice del client è responsabile di stabilire una connessione con il server e inviare richieste ad esso. Nel caso di un codice Dylb, il client è incorporato direttamente nel codice stesso.
To create a client inside a Dylb code, you can use the following steps:
Per creare un client all'interno di un codice Dylb, è possibile seguire i seguenti passaggi:
1. Import the necessary libraries or modules required for establishing a network connection.
Importare le librerie o i moduli necessari per stabilire una connessione di rete.
2. Define the server's IP address and port number to establish a connection.
Definire l'indirizzo IP del server e il numero di porta per stabilire una connessione.
3. Create a socket object to establish a connection with the server.
Creare un oggetto socket per stabilire una connessione con il server.
4. Use the socket object to send requests to the server.
Utilizzare l'oggetto socket per inviare richieste al server.
5. Receive and process the server's response.
Ricevere e elaborare la risposta del server.
Here is an example of a client code inside a Dylb code:
Ecco un esempio di codice client all'interno di un codice Dylb:
```python
import socket
# Define server IP address and port number
server_ip = "192.168.0.1"
server_port = 8080
# Create a socket object
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Establish a connection with the server
client_socket.connect((server_ip, server_port))
# Send a request to the server
request = "Hello, server!"
client_socket.send(request.encode())
# Receive and process the server's response
response = client_socket.recv(1024).decode()
print("Server response:", response)
# Close the connection
client_socket.close()
Make sure to replace the server_ip and server_port variables with the actual IP address and port number of the server you want to connect to.
Assicurarsi di sostituire le variabili server_ip e server_port con l'effettivo indirizzo IP e numero di porta del server a cui si desidera connettersi.