[하루한줄] CVE-2024-21310: Microsoft Cloud Filter Driver의 Numeric Truncation으로 인한 Pool Overflow 취약점

URL

Target

Explain

해당 취약점은 먼저 윈도우에서 긴 경로를 활성화해야 트리거할 수 있습니다.

NtCreateFile 함수는 HsmiQueryFullFilePath 함수에 경로를 전달하게 됩니다.

InformationFile = HsmiQueryFullFilePath(v22, v23, Object, 257i64, &PathSize); [1]
      HsmDbgBreakOnStatus((unsigned int)InformationFile);
      if ( InformationFile < 0 )
      {
        if ( WPP_GLOBAL_Control != (PDEVICE_OBJECT)&WPP_GLOBAL_Control
          && (HIDWORD(WPP_GLOBAL_Control->Timer) & 1) != 0
          && BYTE1(WPP_GLOBAL_Control->Timer) >= 2u )
        {
          WPP_SF_qqd(
            WPP_GLOBAL_Control->AttachedDevice,
            183i64,
            &WPP_78064aab483a35e2f1ef7b76ba44fd52_Traceguids,
            a2,
            v21,
            InformationFile);
        }
        goto LABEL_93;
      }
      v24 = PathSize + *(_WORD *)(a2 + 0x40); [2]

[1]에서 8바이트 크기인 int64 타입의 PathSize에 길이를 저장해 반환합니다.

반환된 PathSize는 [2]에서 연산을 한번 거치게 되는데 이 때 두 숫자를 연산해 결과를 저장하는 변수 v24는 2바이크 크기의 int16 타입의 변수로 하위 값들만 저장되게 됩니다.

따라서 PathSize와 a2 + 0x40 값의 합이 2바이트를 표현할 수 있는 최대값인 0xFFFF를 넘어간다면 Integer Overflow가 발생해 실제보다 작은 값이 저장됩니다.

LOWORD(v39) = 0;
WORD1(v39) = v24;
P = ExAllocatePoolWithTag(PagedPool, v24, 'sUsH'); [3]
InformationFile = P == 0i64 ? 0xC000009A : 0;
HsmDbgBreakOnStatus((unsigned int)InformationFile);
if ( !P )
{
  if ( WPP_GLOBAL_Control != (PDEVICE_OBJECT)&WPP_GLOBAL_Control
    && (HIDWORD(WPP_GLOBAL_Control->Timer) & 1) != 0
    && BYTE1(WPP_GLOBAL_Control->Timer) >= 2u )
  {
    WPP_SF_qd(
      WPP_GLOBAL_Control->AttachedDevice,
      184i64,
      &WPP_78064aab483a35e2f1ef7b76ba44fd52_Traceguids,
      a2,
      InformationFile);
  }
  goto LABEL_93;
}
memmove(P, *(const void **)(a2 + 72), *(unsigned __int16 *)(a2 + 64));
LOWORD(v39) = *(_WORD *)(a2 + 64) - 2;
memmove((char *)P + (unsigned __int16)v39, Src, (unsigned __int16)PathSize); [4]

연산된 v24는 [3]에서 Pool을 할당하는데 사용되는데, 실제 연산된 값보다 작은 Pool이 할당되고 [4]에서 PathSize 만큼의 데이터를 복사하게 되어 Pool Overflow가 발생합니다.

해당 취약점은 RTLUShortAdd 함수를 사용해 두 값이 더해졌을 때 Overflow가 발생하는 확인하는 과정을 추가해, Overflow가 발생할 경우 USHORT의 최대값으로 설정되도록 수정되었습니다.

InformationFile = RtlUShortAdd(pusResult[1], (USHORT)PathSize[0], &pusResult[1]);