[하루한줄] CVE-2023-6779/CVE-2023-6780: glibc Heap Buffer Overflow와 패치된 코드의 Integer Overflow

URL

syslog: Fix heap buffer overflow in __vsyslog_internal (CVE-2023-6779)

syslog: Fix integer overflow in __vsyslog_internal (CVE-2023-6780)

Target

  • glibc 2.36 이상

Explain

GNU C library인 glibc에서 발견된 Heap Buffer Overflow 취약점 및 패치된 코드의 추가적인 Integer Overflow 취약점의 세부 정보가 공개되었습니다.

첫 번째 취약점(CVE-2023-6779)은 syslog.c파일의 __vsyslog_internal 함수에서 snprintf/vsnprintf를 사용하며 메모리 할당 사이즈를 계산하는 과정에서 발생합니다.

void __vsyslog_internal (int pri, const char *fmt, va_list ap, unsigned int mode_flags)
{
//...
	
		vl = __vsnprintf_internal (pos, len, fmt, apc, mode_flags);   // (1)
		
		if (!(0 <= vl && vl < len))
		  buf = NULL;
		
		bufsize = l + vl;   // (2)
		va_end (apc);
	}
	if (buf == NULL)
	{
		buf = malloc ((bufsize + 1) * sizeof (char)); // (3)

//... 
  1. __vsnprintf_internal 함수는 copy한 크기를 리턴하며, 함수 호출에 실패하면 -1를 반환합니다.
    1. 취약한 코드는 리턴값을 vl에 저장하므로 함수 호출 실패 시 vl-1이 될 수 있습니다.
  2. bufsizevl을 이용해 계산되기 때문에 예상보다 작게 계산됩니다.
  3. bufsize+1만큼 할당되는 buf 가 예상보다 작게 할당돼 이후 buf에 copy하는 과정에서 Heap Buffer Overflow가 트리거될 수 있습니다.

CVE-2023-6779 취약점은 아래와 같이 vl0보다 작은 경우 더 이상 메모리 할당 및 copy를 진행하지 않는 것으로 이루어졌습니다.

void __vsyslog_internal (int pri, const char *fmt, va_list ap, unsigned int mode_flags)
{
//...

		vl = __vsnprintf_internal (pos, len, fmt, apc, mode_flags);
		va_end (apc);

		if (vl < 0)             
			goto out;

		if (vl >= len)
			buf = NULL;

		bufsize = l + vl;
	}
	if (buf == NULL)
	{
		buf = malloc ((bufsize + 1) * sizeof (char));

//... 

그러나 위 패치된 코드에서도 추가로 Integer Overflow 취약점이 발견되어 CVE-2023-6780이 할당되었습니다.

vlINT_MAX 값보다 큰 경우 이를 검증하는 코드가 없어 발생하는 Integer Overflow 취약점으로, CVE-2023-6779와 마찬가지로 bufsize 계산에 영향을 주어 이후 Heap Buffer Overflow로 이어질 수 있습니다.

최종적으로 vlINT_MAX - 1 이상인지 검증하는 코드를 추가하는 것으로 패치가 이루어졌습니다.

void __vsyslog_internal (int pri, const char *fmt, va_list ap, unsigned int mode_flags)
{
//...

		vl = __vsnprintf_internal (pos, len, fmt, apc, mode_flags);
		va_end (apc);

		if (vl < 0 || vl >= INT_MAX - 1)
			goto out;

		if (vl >= len)
			buf = NULL;

		bufsize = l + vl;
	}
	if (buf == NULL)
  	{
    	buf = malloc ((bufsize + 1) * sizeof (char));

//...