flawopen.com/Teardowns/cve-2023-6246-glibc-syslog-heap-buffer-overflow
CVE-2023-6246: glibc syslog 힙 버퍼 오버플로
CVE-2023-6246은 긴 로그 헤더로 발생하는 glibc syslog 힙 오버플로입니다. 배포판의 수정된 glibc 패키지를 설치하세요.
짧은 자로 소포와 배송 라벨을 재는 직원을 떠올려 보세요. 라벨이 자에 들어가지 않아 필요한 공간이 계산에 기록되지 않습니다. 직원은 아주 작은 상자를 주문한 뒤 라벨과 내용 전체를 그 안에 인쇄하려 합니다. 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 공격은 아닙니다.
단계별 공격 실행 흐름
로컬 전제 조건
로컬 프로세스가 영향을 받는 glibc를 사용하는 프로그램을 통해 syslog() 또는 vsyslog()를 호출해야 합니다. 보안 영향에는 권한 있는 호출자와 프로그램 이름 접두부를 안전하고 제한된 식별자로 바꾸지 않는 경로가 필요합니다.
긴 헤더
헤더가 초기 버퍼보다 큼|SYSLOG_HEADER에는 긴 프로그램 이름(argv[0]의 basename에서 파생된 __progname) 또는 긴 openlog() 식별자가 포함됩니다. Qualys에 따르면 트리거 값은 1,024바이트를 넘어야 합니다.
크기 계산 누락
크기 계산 분기를 건너뜀|헤더가 1,024바이트 스택 버퍼에 들어가지 않으면 취약한 코드가 bufsize 계산 분기를 건너뜁니다. 이후 힙 할당에 헤더와 포맷된 메시지를 담을 공간이 부족합니다.
메모리 영향
쓰기 작업이 할당 범위를 초과|로거가 너무 작은 버퍼에 헤더와 메시지를 기록해 힙 메모리를 손상시킵니다. 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;
엔지니어링 및 시스템 보안 강화 체크리스트
- ✓배포판과 릴리스에 맞는 수정 glibc 패키지를 설치하세요. upstream 버전만으로 패키지 상태를 판단하지 마세요.
- ✓배포판 보안 공지를 확인하세요. upstream 수정 버전은 glibc 2.39, 2.38-42, 2.37-57, 2.36-126입니다.
- ✓
syslog()또는vsyslog()를 호출하는 권한 있는 프로그램을 조사하고 호출자 제어 이름이나openlog()식별자가 헤더에 들어가는지 확인하세요. - ✓포맷된 로깅에서 초기 고정 버퍼가 부족해도 헤더와 본문의 전체 크기를 계산하세요. 긴 프로그램 이름 회귀 테스트를 추가하고 할당 크기 연산을 검토하세요.