[3] Highlight API iterator-invalidation UAF in clearFromSetLike
Severity: High | Component: CSS Custom Highlight API | 13d284a
이 취약점이 High로 평가된 이유는, document teardown 과정에서 실제 use-after-free가 발생한 것이 ASAN crash(Highlight::clearFromSetLike)로 확인되었기 때문입니다. repaintRange()를 통한 re-entrant 수정 경로는 WebKit의 synchronous layout 모델을 고려했을 때 이론적으로 가능합니다. 다만 controlled read/write primitive로의 확장은 re-entrant window 동안 heap reclamation이 필요한데, 아직 검증되지 않았지만 아키텍처상으로는 가능성이 존재합니다.
이 수정은 이전 embargoed patch에 대한 후속 fix입니다. clearFromSetLike()는 이제 순회를 시작하기 전에 std::exchange를 통해 m_highlightRanges의 내용을 stack-local 임시 변수로 옮깁니다. 따라서 repaintRange() callback 도중 멤버에 re-entrant 수정이 발생하더라도, 이미 비워진 컨테이너에 대한 동작이 됩니다.
Source/WebCore/Modules/highlight/Highlight.cpp
void Highlight::clearFromSetLike()
{
- for (auto& highlightRange : m_highlightRanges)
+ for (auto& highlightRange : std::exchange(m_highlightRanges, { }))
repaintRange(highlightRange->range());
m_highlightRanges.clear();
}
Patch Details
이 변경은 단 한 줄로 이루어집니다. 순회 대상을 m_highlightRanges 대신 std::exchange(m_highlightRanges, { })로 교체했습니다. 이 표현식은 vector의 내용을 임시 변수로 원자적으로 이동시키고, 원래 멤버를 빈 상태로 만듭니다. loop body인 repaintRange(highlightRange->range())는 변경되지 않았습니다. 마지막 줄의 m_highlightRanges.clear()는 이제 no-op이 되었지만(멤버가 이미 비어 있으므로), 방어적 코드로 남아 있습니다.
Background
CSS Custom Highlight API는 JavaScript에서 AbstractRange를 포함하는 Highlight 객체를 생성할 수 있게 해 주며, 이 객체들은 document의 HighlightRegistry에 등록됩니다. highlight가 지워질 때(clearFromSetLike), 각 range는 시각적 강조 표시를 제거하기 위해 repaint되어야 합니다. repaintRange()는 해당 range와 교차하는 DOM 노드를 탐색하며 각각에 대해 renderer->repaint()를 호출합니다. 이 과정에서 WebKit의 synchronous layout 모델에 따라 style 재계산과 layout이 동기적으로 유발될 수 있습니다.
std::exchange(obj, {})는 단일 표현식에서 obj의 값을 꺼내고 기본 생성된 빈 값으로 교체한 뒤 원래 값을 반환하는 C++ idiom입니다. WebKit에서 이 drain-before-iterate 패턴은 re-entrant container 수정에 대한 방어적 관용구로 널리 확립되어 있습니다.
Analysis
Callback을 호출하는 순회 loop 도중 live container에 re-entrant 수정이 발생해 iterator가 무효화된 패턴.
패치 이전에는 clearFromSetLike()가 각 요소에 repaintRange()를 호출하면서 live m_highlightRanges 멤버를 직접 순회했습니다. repaintRange()는 교차하는 노드를 탐색하며 renderer->repaint()를 호출하는데, 이 과정에서 style 재계산, layout, 기타 repaint 부작용이 동기적으로 유발될 수 있습니다.
이런 repaint callback은 m_highlightRanges를 re-entrant하게 수정할 수 있습니다. 예를 들어 observer callback이나 highlight set을 변경하는 다른 코드 경로를 통해 range가 추가되거나 제거되는 상황이 가능합니다. 이것이 re-entrancy boundary에 해당합니다. native code가 layout/style 처리 체계를 호출하면, 그 처리가 반환되기 전에 동기적으로 다시 진입해 객체 상태를 변경할 수 있는 지점입니다.
이런 re-entrant 수정이 발생하면 순회 도중 iterator가 무효화됩니다. 결과적으로 vector의 backing store에 대한 use-after-free 또는 out-of-bounds access로 이어집니다. ASAN crash 시그니처(Highlight::clearFromSetLike; HighlightRegistry::clear; Document::commonTeardown)를 통해 이 경로가 document teardown 중에 실제로 도달 가능함이 확인되었습니다.
Aaaa Aa Aaaaaa Aaa Aaaaaaaaaaaa Aaa Aa Aaaaaaaaaaaaaaaaa Aaaaaaaaaa Aaaaaaaaa Aaaa Aaa Aaaaaa Aa Aa Aaaaaaaaaaaa Aaaaaaaaa Aaaaaaa a Aaaaa Aaaaa Aaaaaaaa Aa Aaaaaaaaaaaa Aaaaa Aaaa Aaaaa Aa a Aaaaa a Aaaa Aaaaaaaaaaaaaaaaaaaa Aaaa Aaaaaaaaaa Aaaa Aa Aaaaaa Aaaaaaa Aaaaaa Aa Aaaaaaaaa Aaaaaaa Aaaa Aaa Aaaaaaaaaaaaaaa Aaaaa Aaa Aaaaaa Aaaaa a Aaaaaaaaaa Aaaaaaaa Aaaaa Aaa Aa Aaaaa Aaa Aaaaa Aaa Aaaaaa
Aaaaaaaaaa Aaaaaaaa Aa Aaaaaaa Aaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaa Aaaaa Aaa Aaa a Aaaaa a Aa Aaaaa Aaaaaaaaa Aaaa Aaa Aa a Aa Aaaa Aaaa Aa Aaaa Aaaa Aaaaaaaaaa Aaaaaa Aaaa Aaaaa Aaaaa Aaaaaaaaaa Aa Aaa Aaaaa Aaaaa Aaaaaaaaaaa Aaa Aaaa Aaaaa Aa Aaa Aaaa Aaaaaaaaaa Aaaaaa Aa Aa Aaa Aaaaaa Aaaa Aaa a Aaaa Aa Aaaaa Aaaaaa Aa Aaaaaaaa Aa Aaaaaaaaaa Aaaaaaaaaa Aaaaaaaaaaa Aaa Aaa Aaaaaa Aaaaaaa Aaaaaa Aaaaa Aaaa Aaaaaaaaa Aaaaa Aaaaa Aaaaa Aa Aaaa Aa Aaaaaa
a Aaaa Aaaaaaaa Aaaaaaaa Aaa Aaaa Aaaaaaa Aaaaaaaaaa Aa Aaa Aaa a Aa Aaaa Aaaaaaaaa Aaaaaaaaaaaaaaa Aaa Aaaa Aa Aaa Aaaaaaaaaa Aaaaaaa Aaaaaaa Aaa Aaaa Aaaaaaaaaa Aaa Aaaa Aaaaa
Aa Aa Aaa Aa Aaaaaaaaaaaaaaaaaaaa Aa Aa Aaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaa Aaaa Aaaaaaaaa Aaaaaaaaa Aaaaaaa Aaaa Aaaaaaaaaaaa Aaa a Aaaa Aa Aaa Aaa Aaa Aaaa Aaaaa
🔒The ownership model and escalation potential of this iterator-invalidation bug are explored in depth
더 확인하려면 구독해 주세요
Audit directions
a Aaa Aa Aaaaa Aaaaa Aaa Aaaaa Aaaaa Aaaa Aaa a Aa Aaa Aaaa Aaa Aaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaa Aaaa Aaaaaaa Aa Aa Aaaa Aa Aaaa Aaa a Aaaaa Aaaaaaaa Aa Aaaaaaaaa a Aaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaa Aaaa Aa Aaa Aaaa Aaaaa Aaaa Aaaa Aa Aaaaa Aaaa Aaaaaaa Aaaaaaaa Aaaa Aaa Aaaaa Aaaaa Aaaaaaaaaaaaaaaa Aaaa Aaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaa Aaa a Aaa Aaaaa
a Aaa Aa Aaaaaaaaa Aaaa Aaaaaaa Aa Aaaaa Aaaa Aaaa Aaa Aa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaa Aaaaaa Aaaa Aaaaaaaaaaaaaaaaa Aaaaaa a Aaaaaaaaaa Aaaa Aaaaaaa Aaa Aa Aaa Aaaa Aaaaaa Aaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaa Aa Aaaaaaaaaa Aaa Aaa a Aaaa Aaaaaaaaaaaaaaaaaaaaa Aa Aa Aaa Aaaa Aaaaa Aaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaa Aaaaaaaaa Aa Aa Aa a Aaaaaaaaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaa Aaa Aaaa Aaa Aaaa Aaaa
a Aaa Aaaaaaaa Aaaaaaaaa Aaaa Aaaaaaaaaa Aa Aaaaaaaaa Aaaa Aaa Aaaaaaaa Aaaa Aaaaaaaaaa Aaaa Aaaa Aaaa Aaa Aaa a Aaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaa Aa Aa a Aaaaaaaaa Aaaa Aa Aaaaaaaaaaaaaaaa Aaaaa Aaa Aaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaa Aaaaaaa Aaaa Aaaa Aa Aaaaa
Aaaaaaaaa Aaaaaaaaaaaaaaaaa Aa Aaaaaaaaaa Aa Aaa Aaaaaa Aa Aaa Aa Aaa Aaaaaaa Aaaaaaaaaaa Aaaaaa Aaaaa Aaa Aaaaaa Aa Aaaaa Aaa Aaa Aaaaa Aaaa Aaaaa Aaa Aaaaa Aaa Aa Aaaaaaaa
🔒Multiple reusable audit patterns identified, with concrete starting points for variant discovery across WebCore
더 확인하려면 구독해 주세요