CVE-2023-6246: syslog Heap Buffer Overflow

Vulnerability Summary

FieldValue
CVECVE-2023-6246
CVSS7.8 (High)
Affectedglibc >= 2.36
Disclosed2024-01-30
TypeHeap-based buffer overflow in __vsyslog_internal()

A heap-based buffer overflow in glibc's __vsyslog_internal() function, called by syslog() and vsyslog(). When openlog() is not called (or called with ident set to NULL) and the program name (argv[0]) exceeds 1024 bytes, the function overflows a heap buffer. Discovered by Qualys.

Exploitation Technique

The exploit targets su, a common SUID-root program:

  1. Execute su with an extremely long argv[0] (> 1024 bytes)
  2. PAM calls syslog() on authentication failure without calling openlog() first
  3. __vsyslog_internal() copies the program name into a heap buffer without proper bounds checking
  4. The overflow corrupts adjacent heap chunk metadata (size, flags, prev_size)
  5. Subsequent heap operations trigger controlled writes via techniques like unsafe unlink
  6. Achieve local privilege escalation to root

The key enabler: glibc stores malloc metadata (chunk headers) inline, directly adjacent to user data. An overflow from one allocation silently corrupts the metadata of the next chunk.

Proof of Concept

Source: tests/cve/heap_overflow.c

The PoC simulates the syslog overflow pattern: allocate a buffer and write past its end.

gcc -o /tmp/heap_overflow tests/cve/heap_overflow.c

glibc output

=== Heap Buffer Overflow Detection Demo ===
    (CVE-2023-6246 pattern)

[1] malloc(100) => 0x...
[2] memset(0x..., 'X', 120) => overflow by 20 bytes!
[3] free(0x...)    => queued for deferred canary check
[4] Triggering batch flush (70 frees)...

[!] Heap overflow was NOT detected on free().
    Under glibc, the adjacent chunk's metadata may be
    silently corrupted, enabling exploitation.

glibc does not detect the overflow. The 20 extra bytes silently overwrite whatever follows the allocation in memory.

compatmalloc output

=== Heap Buffer Overflow Detection Demo ===
    (CVE-2023-6246 pattern)

[1] malloc(100) => 0x...
[2] memset(0x..., 'X', 120) => overflow by 20 bytes!
[3] free(0x...)    => queued for deferred canary check
[4] Triggering batch flush (70 frees)...
compatmalloc: heap buffer overflow detected (canary corrupted)

compatmalloc detects the overflow when the canary bytes are checked during batch verification.

What compatmalloc catches

  1. Canary bytes. For malloc(100), compatmalloc returns a 112-byte slot. Bytes [100..112) contain canary values derived from a cryptographic secret. The 20-byte overflow destroys these canaries. On free(), the canary check detects the corruption and aborts.

  2. Out-of-band metadata. Even if the overflow extends past the slot boundary, it cannot corrupt allocator metadata because metadata is stored in a separate mmap region. The fundamental unsafe-unlink exploitation technique (corrupting inline chunk headers) is not possible.

  3. Guard pages. For overflows that extend past the end of a slab region, guard pages (PROT_NONE) trigger a hardware fault (SIGSEGV). This provides immediate detection without waiting for free().

What compatmalloc does NOT catch

  • The overflow is detected on free(), not at the moment of the write. Between the overflow and the canary check, the program continues executing with corrupted memory. If exploitation completes before free() is called, the canary check may come too late.
  • compatmalloc does not fix the syslog() bug. Using compatmalloc as LD_PRELOAD prevents heap corruption from being exploitable, but the buffer overflow in __vsyslog_internal() still occurs.
  • Intra-slab overflows between adjacent slots in the same slab are detected by canaries, not guard pages. An overflow that exactly fills the canary gap and stops would not be detected (though this is difficult to achieve in practice without knowing the canary secret).

References