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.

💡 通俗通俗化解析 (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.

核心概念与底层架构术语

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.

攻击利用全流程逐步拆解

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.

源码对比:致命缺陷 vs. 加固补丁

采用清晰易读的高级编程语言展示(不含晦涩汇编或二进制机器码)。

未修补缺陷代码
// 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;
}
安全加固补丁
// 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;
}

工程落地与系统加固清单

← 浏览完整安全目录 所有平台安全更新 →