[하루한줄] CVE-2021-30858: Webkit의 UAF 취약점
URL
CVE-2021-30858: Use-after-free in WebKit
Target
- iOS < 14.8, Safari < 14.1.2
Explain
브라우저 엔진인 Webkit에서 발견된 UAF 취약점의 세부 정보가 공개되었습니다.
취약점은 웹페이지에 폰트 리소스를 동적으로 로드하는 CSS Font Loading API에서 발생합니다. FontFace Lookup Table에 등록된 폰트를 제거하는 CSSFontFaceSet::removeFromFacesLookupTable
메서드의 코드는 아래와 같습니다.
void CSSFontFaceSet::removeFromFacesLookupTable(const CSSFontFace& face, const CSSValueList& familiesToSearchFor)
{
...
auto iterator = m_facesLookupTable.find(familyName);
ASSERT(iterator != m_facesLookupTable.end()); // Release 모드 컴파일 시 주석처리
bool found = false;
for (size_t i = 0; i < iterator->value.size(); ++i) {
if (iterator->value[i].ptr() == &face) {
found = true;
iterator->value.remove(i);
break;
}
}
ASSERT_UNUSED(found, found);
if (!iterator->value.size())
m_facesLookupTable.remove(iterator);
}
}
Lookup Table에서 폰트를 제거할 때 일치하는 폰트가 없으면 조건이 일치하지 않는 경우 예외를 발생시키는 ASSERT
문을 사용해 종료했습니다. 그러나 ASSERT
는 디버깅 용도로, 디버그 모드에서만 작동하며 릴리즈 모드에서는 자동으로 주석 처리되어 작동하지 않습니다. 따라서 폰트를 Lookup Table에서 찾지 못해도 이를 제거하려고 시도합니다.
아래는 취약점의 PoC입니다.
var fontFace1 = new FontFace("font1", "", {});
var fontFaceSet = new FontFaceSet([fontFace1]);
fontFace1.family = "font2";
위와 같이 유효하지 않은 FontFace
객체를 생성한 뒤 FontFaceSet
으로 등록해도 Lookup Table에 폰트가 추가되지 않지만 removeFromFacesLookupTable
에서는 ASSERT
가 작동하지 않아 에러 없이 추가되지 않은 폰트를 제거하려고 시도하게 되고 UAF가 트리거됩니다.
취약점은 ASSERT
를 if
문으로 대체해 iterator == m_facesLookupTable.end()
인경우 폰트 제거를 진행하지 않고 함수를 종료하는 것으로 패치되었습니다.
- ASSERT(iterator != m_facesLookupTable.end());
+ if (iterator == m_facesLookupTable.end()) {
return;
}
추가 정보
(21/10/21) 해당 취약점은 CVE-2021-30858로 명명된 취약점이 아닌 다른 취약점이라는 정보가 업데이트되었습니다.
본 글은 CC BY-SA 4.0 라이선스로 배포됩니다. 공유 또는 변경 시 반드시 출처를 남겨주시기 바랍니다.