CVE-2023-6246 / Qualys Advisory

CVE-2023-6246: Glibc __vsyslog_internal Heap Buffer Overflow Teardown

How an off-by-one calculation in Glibc's syslog logging routine allowed local users to overwrite heap buffers via su or sudo, achieving root privileges.

💡 Einfache Erklärung (ELI5)

Imagine a mail room clerk who measures packages before putting them in boxes. If a package is 10 inches, he grabs a 10-inch box. But he forgot that the company always slaps a 3-inch shipping label on top! When he shoves the package into the box, it tears through the sides and crushes the fragile master safe sitting on the shelf next to it.

Kernkonzepte und Subsystem-Begriffe

GNU C Library (Glibc)
The fundamental core library providing the standard C runtime for nearly all Linux distributions.
__vsyslog_internal()
The internal Glibc function responsible for formatting and sending diagnostic messages to the system logging daemon.
Heap Overflow
Writing bytes past the allocated boundary of a dynamically allocated heap memory chunk.
argv[0] Manipulation
Passing an unusually large process invocation name to an executable, altering the prefix in syslog output.

Schritt-für-Schritt Angriffsmechanik

Step 1

1. Process Invocation with Huge Name

The attacker invokes a setuid binary like su with a 1024-byte argv[0] string.

Step 2

2. Triggering Error Logging

The attacker provides invalid credentials, prompting syslog() to format an error message.

Step 3

3. Buffer Undersizing in vsyslog

__vsyslog_internal() calculates the buffer size without properly accounting for the long program name.

Step 4

4. Heap Memory Corruption

The formatted message overflows into neighboring heap metadata, executing attacker shellcode as root.

Quellcode: Kritische Schwachstelle vs. Sichere Behebung

In lesbarem High-Level-Quellcode bereitgestellt (kein rohes Assembler oder Binär-Diff).

UNGEPATCHTE SCHWACHSTELLE
// VULNERABLE: sysdeps/posix/syslog.c before patch
int __vsyslog_internal(int pri, const char *fmt, va_list ap, unsigned int mode_flags) {
    size_t l = strlen(program_invocation_short_name);
    // ROOT CAUSE:
    // When reallocating the log buffer, the code adds 'l' to the length,
    // but under multi-threaded logging or long format strings, 'l' is truncated!
    char *buf = malloc(l + 1024);
    if (!buf) return -1;
    
    // Writes formatted string into undersized buffer!
    int len = vsnprintf(buf, l + 1024, fmt, ap);
    return len;
}
GEHÄRTETER PATCH
// SECURE: sysdeps/posix/syslog.c patch
int __vsyslog_internal(int pri, const char *fmt, va_list ap, unsigned int mode_flags) {
    size_t l = strlen(program_invocation_short_name);
    
    // 1. Explicitly verify integer overflow bounds before allocating
    size_t total_size;
    if (__builtin_add_overflow(l, 1024, &total_size)) {
        return -1; // Reject dangerous oversized buffer
    }
    
    char *buf = malloc(total_size);
    if (!buf) return -1;
    
    // 2. Pass strictly validated total_size to vsnprintf
    int len = vsnprintf(buf, total_size, fmt, ap);
    return len;
}

Engineering-Checkliste zur Systemhärtung

← Sicherheitsverzeichnis durchsuchen Alle Sicherheitsupdates →