← All issues

[6] [WebCore] Fix UAF in Range::createContextualFragment via Trusted Types policy callback

Severity: High | Component: WebCore DOM Range | 1e11f2a

Range::createContextualFragment의 Trusted Types createHTML callback 구간에 걸쳐 raw Node*/Element* 캡처가 Ref/RefPtr로 승격되었기 때문에 High로 분류됩니다. 승격이 없는 상태에서는 attacker가 policy callback 내의 JS를 통해 모든 reference를 해제하고 GC를 강제할 수 있었습니다. callback이 반환된 이후 해당 pointer를 역참조하면 이미 해제된 메모리를 대상으로 동작하게 됩니다.

Range::createContextualFragment에서 캡처된 Node/Element reference가 Ref/RefPtr로 변환되어, Trusted Types policy 호출 구간 전반에 걸쳐 lifetime이 고정됩니다.

Source/WebCore/dom/Range.cpp

- auto* node = startContainer.get();
+ Ref node = startContainer;
...
auto sanitized = trustedTypes->createHTML(input);
// attacker JS가 range를 변경하거나 ref를 해제하고 GC를 강제할 수 있음
- parse(*node, sanitized);
+ parse(node.get(), sanitized);

Re-entrancy UAF: Trusted Types policy callback 호출 전 raw Node pointer를 캡처하고, attacker JavaScript 동기 실행 이후 해당 pointer를 역참조하는 패턴.

context node와 start container에 대한 함수의 로컬 캡처가 reference-counted 형태로 변경되었습니다. policy callback 자체에는 수정이 없습니다.

Range::createContextualFragment는 Range의 start container 컨텍스트 안에서 HTML fragment를 파싱합니다. Trusted Types의 createHTML policy는 입력 문자열 경로상에 위치하며, 파싱 전에 사용자가 등록한 JavaScript callback을 실행하여 제공된 HTML을 sanitize합니다.

패치 이전에는 함수가 Range의 boundary에서 raw Node*/Element*를 추출한 뒤, createHTML 호출을 거치는 동안에도 그대로 사용하는 구조였습니다. 이 callback은 attacker가 제어하는 JS입니다. callback 내에서 Range를 변경할 수 있습니다. 예를 들어 range.setEnd(document, 0)을 호출하면, 구현상 순서가 역전될 때 setEnd가 start를 end 위치로 이동시킵니다. 이 밖에도 살아있는 모든 reference를 해제하고 GC를 강제하는 것도 가능합니다.

🔒

Detailed analysis of how Trusted Types reshapes the re-entrancy model of DOM string sinks, and the realistic exploitation path for the resulting UAF.

더 확인하려면 구독해 주세요

🔒

Four reusable audit patterns identified across DOM string sinks, Range/Selection consumers, and GC-driven finalization, with concrete grep starting points.

더 확인하려면 구독해 주세요