macOS XPC
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
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 diversi processi sul sistema. Fa parte del paradigma di sicurezza di Apple, consentendo la creazione di applicazioni separate per privilegi in cui ogni componente viene eseguito con solo i permessi necessari per svolgere il proprio lavoro, limitando così il potenziale danno derivante da un processo compromesso.
XPC utilizza una forma di Inter-Process Communication (IPC), che è un insieme di metodi per diversi programmi in esecuzione sullo stesso sistema per inviare dati avanti e indietro.
I principali vantaggi di XPC includono:
Sicurezza: Separando il lavoro in diversi processi, a ciascun processo possono essere concessi solo i permessi necessari. Ciò significa che anche se un processo viene compromesso, ha una capacità limitata di fare danni.
Stabilità: XPC aiuta a isolare i crash al componente in cui si verificano. Se un processo si blocca, può essere riavviato senza influenzare il resto del sistema.
Prestazioni: XPC consente una facile concorrenza, poiché diversi compiti possono essere eseguiti simultaneamente in processi diversi.
L'unico svantaggio è che separare un'applicazione in più processi facendoli comunicare tramite XPC è meno efficiente. Ma nei sistemi odierni questo non è quasi percepibile e i benefici sono maggiori.
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 estensione .xpc
(come com.apple.Safari.SandboxBroker.xpc
) e sono anche pacchetti con il binario principale all'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à diritti e privilegi diversi rispetto agli altri componenti XPC o al binario principale dell'app. ECCETTO se un servizio XPC è configurato con JoinExistingSession impostato su “True” nel suo Info.plist. In questo caso, il servizio XPC verrà eseguito nella stessa sessione di sicurezza dell'applicazione che lo ha chiamato.
I servizi XPC sono avviati da launchd quando necessario e spenti una volta completati tutti i compiti per liberare risorse di sistema. I componenti XPC specifici dell'applicazione possono essere utilizzati solo dall'applicazione, riducendo così il rischio associato a potenziali vulnerabilità.
I servizi XPC a livello di sistema sono accessibili a tutti gli utenti. Questi servizi, sia launchd che di tipo Mach, devono essere definiti in file plist situati in directory specifiche 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:
I processi in LaunchDameons
vengono eseguiti da root. Quindi, se un processo non privilegiato può comunicare con uno di questi, potrebbe essere in grado di elevare i privilegi.
xpc_object_t
Ogni messaggio XPC è un oggetto dizionario che semplifica la serializzazione e deserializzazione. Inoltre, libxpc.dylib
dichiara la maggior parte dei tipi di dati, quindi è possibile garantire che i dati ricevuti siano del tipo previsto. Nell'API C, ogni oggetto è un xpc_object_t
(e il suo tipo può essere verificato utilizzando xpc_get_type(object)
).
Inoltre, la funzione xpc_copy_description(object)
può essere utilizzata per ottenere una rappresentazione stringa dell'oggetto che può essere utile per scopi di debug.
Questi oggetti hanno anche alcuni metodi da chiamare come xpc_<object>_copy
, xpc_<object>_equal
, xpc_<object>_hash
, xpc_<object>_serialize
, xpc_<object>_deserialize
...
Gli xpc_object_t
vengono creati chiamando la funzione xpc_<objetType>_create
, che chiama internamente _xpc_base_create(Class, Size)
dove viene indicato il tipo della classe dell'oggetto (uno di XPC_TYPE_*
) e la sua dimensione (alcuni extra 40B verranno aggiunti alla dimensione per i metadati). Ciò significa che i dati dell'oggetto inizieranno all'offset di 40B.
Pertanto, il xpc_<objectType>_t
è una sorta di sottoclasse di xpc_object_t
che sarebbe una sottoclasse di os_object_t*
.
Nota che dovrebbe essere lo sviluppatore a utilizzare xpc_dictionary_[get/set]_<objectType>
per ottenere o impostare il tipo e il valore reale di una chiave.
xpc_pipe
Un xpc_pipe
è un tubo FIFO che i processi possono utilizzare per comunicare (la comunicazione utilizza messaggi Mach).
È possibile creare un server XPC chiamando xpc_pipe_create()
o xpc_pipe_create_from_port()
per crearlo utilizzando una porta Mach specifica. Poi, per ricevere messaggi, è possibile chiamare xpc_pipe_receive
e xpc_pipe_try_receive
.
Nota che l'oggetto xpc_pipe
è un xpc_object_t
con informazioni nella sua struct riguardo le due porte Mach utilizzate e il nome (se presente). Il nome, ad esempio, il demone secinitd
nel suo plist /System/Library/LaunchDaemons/com.apple.secinitd.plist
configura il tubo chiamato com.apple.secinitd
.
Un esempio di xpc_pipe
è il bootstrap pipe creato da launchd
che rende possibile la condivisione delle porte Mach.
NSXPC*
Questi sono oggetti di alto livello Objective-C che consentono l'astrazione delle connessioni XPC. Inoltre, è più facile eseguire il debug di questi oggetti con DTrace rispetto a quelli precedenti.
GCD Queues
XPC utilizza GCD per inviare messaggi, inoltre genera alcune code di dispatch come xpc.transactionq
, xpc.io
, xpc-events.add-listenerq
, xpc.service-instance
...
Questi sono bundle con estensione .xpc
situati all'interno della cartella XPCServices
di altri progetti e nel Info.plist
hanno il CFBundlePackageType
impostato su XPC!
.
Questo file ha altre chiavi di configurazione come ServiceType
che può essere Application, User, System o _SandboxProfile
che può definire un sandbox o _AllowedClients
che potrebbe indicare diritti o ID richiesti per contattare il servizio. Queste e altre opzioni di configurazione saranno utili per configurare il servizio al momento del lancio.
L'app tenta di connettersi a un servizio XPC utilizzando xpc_connection_create_mach_service
, quindi launchd localizza il demone e avvia xpcproxy
. xpcproxy
applica le restrizioni configurate e genera il servizio con i FD e le porte Mach forniti.
Per migliorare la velocità di ricerca del servizio XPC, viene utilizzata una cache.
È possibile tracciare le azioni di xpcproxy
utilizzando:
La libreria XPC utilizza kdebug
per registrare azioni chiamando xpc_ktrace_pid0
e xpc_ktrace_pid1
. I codici che utilizza non sono documentati, quindi è necessario aggiungerli in /usr/share/misc/trace.codes
. Hanno il prefisso 0x29
e, ad esempio, uno è 0x29000004
: XPC_serializer_pack
.
L'utilità xpcproxy
utilizza il prefisso 0x22
, ad esempio: 0x2200001c: xpcproxy:will_do_preexec
.
Le applicazioni possono iscriversi a diversi messaggi di evento, consentendo loro di essere iniziati su richiesta quando si verificano tali eventi. La configurazione per questi servizi è effettuata nei file plist di launchd, situati nelle stesse directory di quelli precedenti e contenenti una chiave extra LaunchEvent
.
Quando un processo tenta di chiamare un metodo tramite una connessione XPC, il servizio XPC dovrebbe controllare se quel processo è autorizzato a connettersi. Ecco i modi comuni per controllarlo e le insidie comuni:
macOS XPC Connecting Process CheckApple consente anche alle app di configurare alcuni diritti e come ottenerli, quindi se il processo chiamante li possiede, sarebbe autorizzato a chiamare un metodo dal servizio XPC:
macOS XPC AuthorizationPer intercettare i messaggi XPC, puoi utilizzare xpcspy che utilizza Frida.
Un altro strumento possibile da utilizzare è XPoCe2.
Questa funzionalità fornita da RemoteXPC.framework
(da libxpc
) consente di comunicare tramite XPC tra diversi host.
I servizi che supportano remote XPC avranno nel loro plist la chiave UsesRemoteXPC come nel caso di /System/Library/LaunchDaemons/com.apple.SubmitDiagInfo.plist
. Tuttavia, sebbene il servizio sia registrato con launchd
, è UserEventAgent
con i plugin com.apple.remoted.plugin
e com.apple.remoteservicediscovery.events.plugin
a fornire la funzionalità.
Inoltre, il RemoteServiceDiscovery.framework
consente di ottenere informazioni dal com.apple.remoted.plugin
esponendo funzioni come get_device
, get_unique_device
, connect
...
Una volta utilizzato connect e raccolto il socket fd
del servizio, è possibile utilizzare la classe remote_xpc_connection_*
.
È possibile ottenere informazioni sui servizi remoti utilizzando lo strumento cli /usr/libexec/remotectl
utilizzando parametri come:
La comunicazione tra BridgeOS e l'host avviene attraverso un'interfaccia IPv6 dedicata. Il MultiverseSupport.framework
consente di stabilire socket i cui fd
saranno utilizzati per comunicare.
È possibile trovare queste comunicazioni utilizzando netstat
, nettop
o l'opzione open source, netbottom
.
Impara e pratica Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Impara e pratica Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)