FlawOpen

flawopen.com/Teardowns/cve-2023-6246-glibc-syslog-heap-buffer-overflow

● CVE-2023-6246 · CVSS 7.8 · 높음
보안 연구 · FlawOpen

CVE-2023-6246: glibc syslog 힙 버퍼 오버플로

CVE-2023-6246은 긴 로그 헤더로 발생하는 glibc syslog 힙 오버플로입니다. 배포판의 수정된 glibc 패키지를 설치하세요.

💡 알기 쉬운 설명 (ELI5)

짧은 자로 소포와 배송 라벨을 재는 직원을 떠올려 보세요. 라벨이 자에 들어가지 않아 필요한 공간이 계산에 기록되지 않습니다. 직원은 아주 작은 상자를 주문한 뒤 라벨과 내용 전체를 그 안에 인쇄하려 합니다. glibc에서는 긴 syslog 헤더 때문에 필요한 크기가 기록되지 않아 로거가 힙 메모리를 너무 적게 할당할 수 있었습니다.

핵심 개념 및 용어

glibc
GNU C Library는 대부분의 Linux 프로그램이 사용하는 핵심 C 런타임 함수를 제공합니다.
__vsyslog_internal()
syslog()와 vsyslog()가 메시지와 SYSLOG_HEADER를 포맷해 시스템 로거로 보내는 데 사용하는 glibc 내부 구현입니다.
SYSLOG_HEADER
syslog 메시지 앞에 포맷되는 우선순위 및 식별 접두부입니다. 프로그램 이름이나 openlog()에서 전달한 식별자를 포함할 수 있습니다.
Heap-based buffer overflow (CWE-122)
힙에 할당된 버퍼의 경계를 넘는 쓰기입니다. 여기서는 긴 이름이 포함된 헤더가 초기 고정 버퍼에 들어가지 않을 때 크기 계산이 실패했습니다.

프레임워크 매핑

  • 이 가이드에서 설명하는 약점의 CWE 참조: CWE-122

근본 원인 분석 (Root Cause)

glibc 공지에 따르면 긴 프로그램 이름이 포함된 SYSLOG_HEADER를 출력할 때 __vsyslog_internal()이 필요한 버퍼 크기를 갱신하지 못했습니다. 취약한 코드에서는 헤더 길이 l이 1,024바이트 스택 버퍼 이상일 수 있어 메시지 본문을 포맷하고 bufsize를 설정하는 분기를 건너뛰었습니다. 이후 힙 할당 경로는 설정되지 않았거나 0인 크기를 사용하고 작은 영역에 헤더와 메시지를 기록했습니다. Qualys는 긴 이름이 호출자가 제어하는 argv[0]의 basename 또는 1,024바이트를 넘는 openlog() 식별자에서 올 수 있다고 설명합니다. 이 경로로 로그를 남기는 취약한 setuid 프로그램에서는 보안 영향이 생길 수 있습니다. Qualys는 Fedora 38의 su를 통한 로컬 권한 상승을 입증했습니다. 위험은 로컬 접근, 설정 및 호출 경로에 따라 달라지며 일반적인 원격 syslog 공격은 아닙니다.

단계별 공격 실행 흐름

단계 1

로컬 전제 조건

로컬 프로세스가 영향을 받는 glibc를 사용하는 프로그램을 통해 syslog() 또는 vsyslog()를 호출해야 합니다. 보안 영향에는 권한 있는 호출자와 프로그램 이름 접두부를 안전하고 제한된 식별자로 바꾸지 않는 경로가 필요합니다.

단계 2

긴 헤더

헤더가 초기 버퍼보다 큼|SYSLOG_HEADER에는 긴 프로그램 이름(argv[0]의 basename에서 파생된 __progname) 또는 긴 openlog() 식별자가 포함됩니다. Qualys에 따르면 트리거 값은 1,024바이트를 넘어야 합니다.

단계 3

크기 계산 누락

크기 계산 분기를 건너뜀|헤더가 1,024바이트 스택 버퍼에 들어가지 않으면 취약한 코드가 bufsize 계산 분기를 건너뜁니다. 이후 힙 할당에 헤더와 포맷된 메시지를 담을 공간이 부족합니다.

단계 4

메모리 영향

쓰기 작업이 할당 범위를 초과|로거가 너무 작은 버퍼에 헤더와 메시지를 기록해 힙 메모리를 손상시킵니다. Qualys는 Fedora 38의 su를 통한 로컬 권한 상승을 보였지만 모든 앱이나 배포판의 도달 가능성이 같다고 일반화하지 마세요.

소스 코드 비교: 취약한 구현 vs 보안 패치

이전 분기는 헤더가 스택 버퍼에 들어가지 않으면 bufsize를 0으로 남겨 후속 힙 할당이 부족할 수 있었습니다. 수정은 이 경우 스택 버퍼를 사용할 수 없다고 표시하고, 본문 길이를 측정하도록 포맷한 뒤 l + vl을 기록하고 필요한 크기로 기존 할당 경로를 진행합니다. 이는 upstream 핵심 발췌이며 완전한 독립 함수는 아닙니다.

소스 코드 발췌: misc/syslog.c

취약한 구현
/* 커밋 6bd0e4efcc78 이전 misc/syslog.c의 관련 부분입니다. */
char bufs[1024];
char *buf = NULL;
size_t bufsize = 0;
...
if (0 <= l && l < sizeof bufs)
  {
    va_list apc;
    va_copy (apc, ap);
    int vl = __vsnprintf_internal (bufs + l, sizeof bufs - l, fmt, apc,
                                   mode_flags);
    if (0 <= vl && vl < sizeof bufs - l)
      buf = bufs;
    bufsize = l + vl;
    va_end (apc);
  }
/* 긴 헤더는 위쪽의 크기 설정 분기를 건너뜁니다. */
보안 강화 패치
/* 커밋 6bd0e4efcc78 이후 misc/syslog.c의 관련 부분입니다. */
char bufs[1024];
char *buf = bufs;
size_t bufsize;
...
if (0 <= l && l < sizeof bufs)
  {
    pos = bufs + l;
    len = sizeof (bufs) - l;
  }
else
  {
    buf = NULL;
    pos = bufs;
    len = sizeof (bufs);
  }
vl = __vsnprintf_internal (pos, len, fmt, apc, mode_flags);
if (!(0 <= vl && vl < len))
  buf = NULL;
bufsize = l + vl;

엔지니어링 및 시스템 보안 강화 체크리스트

출처