[하루한줄] CVE-2025-31200 : Apple CoreAudio framework의 OOB Write로 인한 RCE 취약점
URL
Target
영향받는 기기 목록은 애플 취약점 릴리즈 문서 참고
- macOS < 15.4.1
- tvOS < 18.4.1
- visionOS < 2.4.1
- iOS < 18.4.1
- iPadOS < 18.4.1
Explain
background
CVE-2025-31200은 애플 제품의 오디오 파일을 처리하는 CoreAudio의 구성 요소에서 발생하는 OOB Write 취약점입니다. 이를 통한 원격 코드 실행이 가능하며 CVE-2025-31201과 함께 In-the-wild 취약점으로 패치되었습니다.
해당 취약점으로 인해 패치가 진행된 부분은 /System/Library/AudioToolbox.framework/AudioCodecs 내에 존재하는 apac::hoa::CodecConfig::Deserialize()
함수로 이는 공간음향을 지원하기 위한 Apple Positional Audio Codec과 관련된 함수입니다.
이번 취약점을 이해하기 위해서는 추가적으로 Channel remapping에 관한 이해가 필요합니다. 간략하게 설명하면 재생 시스템(스피커, 이어폰)과 소스 스트림(오디오 파일)의 채널을 일치시키기 위해 정렬하는 과정입니다.
root cause
취약점이 트리거 되는 전체 흐름은 다음과 같습니다:
apac::hoa::CodecConfig::Deserialize()
함수 내에서 미흡한 검사로 인해 OOB Write가 발생APACChannelRemapper::Process()
함수를 통한 Channel remapping 수행- 두 번째 인자로 포인터 값이 담긴 배열을 넘겨받으며 이는 순서 정렬에 사용됨
- 순서 정렬 범위의 기준값은
mRemappingArray
배열의 길이
mRemappingArray
의 길이가 전달된 배열의 길이보다 큰 경우 범위를 넘어선 위치에 접근 시도
1cfa068cc int64_t APACChannelRemapper::Process(struct APACChannelRemapper* this, double** floatVector)
1cfa068cc {
1cfa068cc void* mRemappingStart = this->mRemappingStart;
1cfa068cc void* mRemappingEnd = this->mRemappingEnd;
1cfa068cc
1cfa068d4 if (mRemappingStart != mRemappingEnd)
1cfa068d4 {
1cfa068d8 int32_t i = 0;
1cfa068dc int32_t j = 0;
1cfa068dc
1cfa0691c do
1cfa0691c {
1cfa068e0 uint64_t i_1 = i;
1cfa068e0
1cfa068ec do
1cfa068e4 i_1 = (uint64_t)*(uint8_t*)((char*)mRemappingStart + i_1);
1cfa068ec while (j < (uint32_t)i_1);
1cfa068ec
1cfa068f0 if (j != (uint32_t)i_1)
1cfa068f0 {
1cfa068f4 double* x8 = *(uint64_t*)floatVector;
1cfa068f8 double* x9 = x8[i];
1cfa06900 x8[i] = x8[i_1];
1cfa06904 x8[i_1] = x9;
1cfa06908 mRemappingStart = this->mRemappingStart;
1cfa06908 mRemappingEnd = this->mRemappingEnd;
1cfa068f0 }
1cfa068f0
1cfa0690c i = j + 1;
1cfa06914 j = i;
1cfa0691c } while ((char*)mRemappingEnd - mRemappingStart > i);
1cfa068d4 }
1cfa068d4
1cfa06924 return 0;
1cfa068cc }
반복문 실행 시 사용되는 조건을 살펴보면 i가 mRemappingEnd
- mRemappingStart
의 결과보다 작은 값일 때 수행됩니다. 실제 값의 변경이 이루어지는 대상은 floatVector
배열로 이는 포인터 값을 담고 있습니다.
그러나 mRemappingArray
와 floatVector
배열의 크기가 일치하는지에 대한 검사는 존재하지 않기 때문에 만약 실제 데이터를 보관할 수 있는 공간보다 더 많은 데이터 이동을 수행하고자 한다면 의도되지 않은 값이 배열로 위치하거나 반대로 사용자가 입력한 값이 범위를 벗어난 메모리에 위치하게 됩니다.
패치가 수행된 apac::hoa::CodecConfig::Deserialize()
함수를 비교하면 mRemappingArray
에 데이터를 옮길 때 전체 컴포넌트의 수보다 많은 경우 반복문을 중단하도록 추가하여 floatVector
와 동일한 크기를 가질 수 있도록 수정되었습니다.
// ...
*(this->mRemappingArray + cnt) = elem_to_add;
totalComponents = this->totalComponents;
if (totalComponents <= *(this->mRemappingArray + cnt) )
{
os_log(“Invalid mRemappingArray bitstream in hoa::CodecConfig::Deserialize()”);
return 1;
}
if ( ++cnt >= totalComponents )
goto skipbits_and_return; // Patched
}
// ...
Takeaways
이번 취약점의 특별한 점은 그저 특정 위치에 값을 쓰는 것 뿐만 아니라 데이터의 위치 교환이 이루어지기 때문에 동시에 특정 위치의 값을 읽는 것 또한 가능한 벡터라는 특징이 있습니다. 원격 코드 실행을 위한 전체 PoC가 공개되지는 않았지만 CVE-2025-31201과 연계한 PAC 우회가 가능할 것이라 발표된 만큼 관심이 있다면 추가적인 분석을 해보는 것도 좋을 것 같습니다.
Reference
본 글은 CC BY-SA 4.0 라이선스로 배포됩니다. 공유 또는 변경 시 반드시 출처를 남겨주시기 바랍니다.