[2] WebPasteboardProxy missing frame-ancestry check under Site Isolation
Severity: High | Component: WebKit UI-process WebPasteboardProxy (Cocoa) | 69aa562
diff가 공격자 제공 frame identifier에 대한 subtree 소속 검증을 추가한다는 점에서 High로 평가됩니다. 패치 이전에는 손상된 WebContent process가 pasteboard IPC에 임의의 frame identifier를 지정할 수 있었고, 관련 없는 cross-site frame의 직렬화된 DOM이 수집되는 경로가 존재했습니다. 단, sandbox escape은 포함되지 않으며, 영향 범위는 대상 FrameIdentifier를 특정하고 pasteboard를 다시 읽어오는 조건 하의 cross-site 정보 유출에 한정됩니다.
WebPasteboardProxy는 수신한 remote frame ID에 대해 subtree 검증을 전혀 수행하지 않았습니다. 이로 인해 관련 없는 cross-site remote frame의 콘텐츠가 pasteboard에 기록될 수 있었습니다. 이번 수정에서는 WebPasteboardProxy 내에서 사용되는 모든 remote frame ID가 복사 대상 root frame ID의 하위 frame인지 확인하는 message check가 추가되었습니다.
Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm
+// 제공된 root frame에서 파생된 frame만 허용합니다.
+static bool validateFrameIdentifiers(FrameIdentifier rootFrameIdentifier, const HashMap<FrameIdentifier, Ref<WebCore::LegacyWebArchive>>& localFrameArchives, const Vector<FrameIdentifier>& remoteFrameIdentifiers)
+{
+ auto isInSubtree = [&](WebFrameProxy& frame) {
+ for (RefPtr ancestor = &frame; ancestor; ancestor = ancestor->parentFrame()) {
+ if (ancestor->frameID() == rootFrameIdentifier)
+ return true;
+ }
+ return false;
+ };
+ auto isAllowed = [&](FrameIdentifier identifier) {
+ if (identifier == rootFrameIdentifier)
+ return true;
+ RefPtr frame = WebFrameProxy::webFrame(identifier);
+ return !frame || isInSubtree(*frame);
+ };
+ for (auto& [frameIdentifier, archive] : localFrameArchives) {
+ if (!isAllowed(frameIdentifier))
+ return false;
+ Ref protectedArchive = archive;
+ if (auto archiveFrameIdentifier = protectedArchive->frameIdentifier(); archiveFrameIdentifier && !isAllowed(*archiveFrameIdentifier))
+ return false;
+ for (auto subframeIdentifier : protectedArchive->subframeIdentifiers()) {
+ if (!isAllowed(subframeIdentifier))
+ return false;
+ }
+ }
+ for (auto identifier : remoteFrameIdentifiers) {
+ if (!isAllowed(identifier))
+ return false;
+ }
+ return true;
+}
+ // writeWebContentToPasteboard
+ MESSAGE_CHECK(validateFrameIdentifiers(*rootFrameIdentifier, content.localFrameArchives, content.remoteFrameIdentifiers), connection);
+ // writeWebArchiveToPasteBoard
+ MESSAGE_CHECK_COMPLETION(validateFrameIdentifiers(rootFrameIdentifier, localFrameArchives, remoteFrameIdentifiers), connection, completionHandler(WriteWebArchiveToPasteBoardResult::FailureDueToInvalidFrameIdentifiers, 0));
LayoutTests/http/tests/ipc/resources/write-web-archive-frame-ancestry-check-iframe.html
+ // 프로세스 외부의 frame ID(부모 frame)를 remote subframe으로 지정하는
+ // WriteWebArchiveToPasteBoard IPC를 위조합니다. FailureDueToInvalidFrameIdentifiers 오류로 실패해야 합니다.
+ let r = IPC.sendSyncMessage('UI', 0, IPC.messages.WebPasteboardProxy_WriteWebArchiveToPasteBoard.name, 1000, [
+ S(pbName), FrameID(myFrameID), u64(0n), u64(1n), FrameID(parentFrameID),
+ ]);
Patch Details
새로운 static helper validateFrameIdentifiers(rootFrameIdentifier, localFrameArchives, remoteFrameIdentifiers)는 전달된 각 frame identifier를 순회하며, 복사 대상 root frame의 subtree에 속하는지 확인합니다. isAllowed()는 root frame 자체에 대해서는 true를 반환합니다. 그 외의 frame은 WebFrameProxy::webFrame(identifier)로 조회한 뒤, isInSubtree lambda가 parentFrame()을 따라 root까지 거슬러 올라가 ancestry chain이 rootFrameIdentifier에 도달하는지 검증합니다. 알 수 없는(null) frame 역시 허용 대상으로 처리됩니다. 이 helper는 content.localFrameArchives의 모든 key를 검증하며, 각 archive 자체의 frameIdentifier()와 subframeIdentifiers(), 그리고 모든 remoteFrameIdentifiers 항목도 마찬가지로 확인합니다. writeWebContentToPasteboard에는 MESSAGE_CHECK가, writeWebArchiveToPasteBoard에는 MESSAGE_CHECK_COMPLETION이 추가되었습니다. WriteWebArchiveToPasteBoard의 응답 타입은 기존의 단순한 int64_t changeCount에서 (WriteWebArchiveToPasteBoardResult result, int64_t changeCount) 형태로 확장되었습니다. WriteWebArchiveToPasteBoardResult는 Success / FailureDueToInvalidFrameIdentifiers / FailureOther 값을 갖는 새로운 enum class로, WebProcess와 테스트 코드가 거부 결과를 확인할 수 있게 됩니다.
Site Isolation pasteboard broker의 IPC trust boundary를 넘는 공격자 제공 frame identifier에 대한 frame ancestry(subtree 소속) 검증 누락.
Background
Site Isolation은 cross-site iframe을 별도의 WebContent process에 배치하는 WebKit의 아키텍처입니다. 각 frame은 프로세스 전반에 걸쳐 고유한 FrameIdentifier를 가지며, UI process는 이를 통해 frame을 식별합니다. WebPasteboardProxy는 WebContent process를 대신해 pasteboard 작업을 중개하는 UI-process IPC 메시지 수신자입니다. LegacyWebArchive는 frame과 하위 frame을 직렬화한 WebKit의 표현 형식(.webarchive)이며, createOneWebArchiveFromFrames는 root frame과 local frame archive, 그리고 remote(프로세스 외부) subframe identifier를 조합해 하나의 archive를 생성합니다. WebFrameProxy::webFrame(identifier)는 FrameIdentifier를 해당 frame의 UI-process proxy로 변환하며, parentFrame() 체인이 frame tree 구조를 나타냅니다.
MESSAGE_CHECK와 MESSAGE_CHECK_COMPLETION은 IPC 유효성 검사 매크로입니다. 검증 실패 시 해당 메시지를 유효하지 않은 것으로 처리하고, 발신자를 종료하거나 오류를 반환합니다. 공격자가 제어하는 IPC 입력에 대해 불변 조건을 강제하는 표준 메커니즘입니다. IPCTestingAPI는 레이아웃 테스트에서 원시 IPC 메시지를 직접 합성할 수 있게 해주는 테스트 전용 기능으로, 이번 테스트에서는 비하위 frame을 지정하는 요청을 위조하는 데 사용되었습니다.
Analysis
이 취약점은 IPC handler에서 발생한 인가 누락이자 프로세스 간 capability 검증 부재로, Site Isolation 경계 우회에 해당합니다. 패치 이전에는 writeWebArchiveToPasteBoard와 writeWebContentToPasteboard가 IPC 메시지에서 받은 rootFrameIdentifier, 임의의 local frame archive key, remoteFrameIdentifiers를 그대로 createOneWebArchiveFromFrames에 전달했습니다. 해당 identifier들이 rootFrameIdentifier를 root로 하는 subtree에 속하는지는 전혀 확인하지 않았습니다.
Site Isolation 하에서 cross-site subframe은 서로 다른 WebContent process에 존재하지만, FrameIdentifier는 UI process 전반에서 전역적으로 주소를 지정할 수 있습니다. UI process의 WebPasteboardProxy는 다른 frame의 프로세스에 접근해 직렬화된 DOM을 수집하고 multi-frame web archive를 조합하는 신뢰된 중개자입니다. ancestry 검증이 없는 상황에서는, 자신의 frame을 직렬화하는 WebContent process가 전혀 관련 없는 cross-site remote frame을 "remote subframe"으로 지정할 수 있었습니다. 결과적으로 해당 frame의 콘텐츠가 수집되어 pasteboard에 기록될 수 있었습니다.
Aaaaaaaaaa Aaaaa a Aaaa Aa Aaa Aa Aaaaaa Aaaaaaa Aaa Aaaa Aaa Aa Aa Aaaaaa Aaaaaaaaaaaaaaaaaa Aaaaaa Aaaaaaaaaa Aaaa Aaaa Aaaa Aa Aa Aaaa Aa Aaa Aaaaaa Aa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaa Aa Aaaaa Aaaaa Aaaa Aaaaaaaaaa Aaaaaaaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaa Aa Aaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaa Aaaaaaaa Aaaaaaaa Aaaaaaaaaaaaa Aa Aa Aaaaaaaaaa Aaaaaa Aaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaa Aaaaaa Aaaa Aaaa Aaaaaaaa Aaaa Aaaaaaaaaaa Aaaaa Aaa Aaaaa Aa Aa Aaa a Aaaaa Aa Aaaaaaaaaaaaaaaaaa Aa Aaa Aa Aa Aaaaaaaaaa Aaa Aa Aaaaaaaaaa Aaaaaa
a Aaaa Aaaa Aaaaaaaaaa Aaaaaaaaaaa Aaaaa Aaaaaaaaa Aaaaaaa Aa Aaa Aaaaaaaaaa Aaaaaaaa Aa Aa a Aaa Aaaaa Aaaaaaaaa Aaaaaaaaaaa Aaaa a Aaa Aaaa Aaa Aaaaaaa Aaa Aaa Aaaaaa Aaaaaaaa Aaaa Aaaa Aa Aaaaaaaaaa Aaaaaaa Aaaaaa Aa Aaaa a Aa Aaa Aaaa Aaa Aaaa Aaaaaaaaaa Aaaaaaaa Aa Aaaaaaa Aaaaaaaaaaaaa Aaaaa Aaaa Aaa Aaa a Aaaaaa Aa Aaaa Aa Aaaa Aaaaaaaaaaaa Aa Aa Aaa Aaaaa Aaaaaaa Aaaaaaa Aaaaa Aa Aaaaa Aaaaa Aaa Aaa Aaaaa Aa Aaaa Aaaaaaaaaaaaaaaaaaaaa Aa Aa Aaaa Aaaaa Aa Aaaaaaaaaaaaa Aa Aaaaaa Aaa Aa Aaa Aaaaa
Aaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaaaaa Aaa Aa Aa Aaa Aaaaaa Aaaa Aaaaaa Aaa Aaaaaa Aaaa Aa Aaaaa Aaa Aaaa Aaaaaa Aa Aaaa Aaa Aaaaa Aaa Aaa Aa Aaa Aa Aaa Aaa Aa Aa Aaaaaa
🔒Examines how a trusted UI-process broker handled untrusted frame identifiers across the Site Isolation boundary, and what cross-origin exposure the gap allowed.
더 확인하려면 구독해 주세요
Audit directions
a Aaaaaa Aaa Aaaaaaaaaaaaaaaaaa Aaaa Aaaaa Aa Aaaaaaaa Aaaa Aaaaa Aaa Aaaaaa Aaaaaaaaaaaaaaa Aaa Aa Aaaaaaaaaaaaaaaa Aaaa Aa Aaaaaaaaaa Aaa Aaaaaaaaaa Aaaa Aaaaaaaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaaaaaaaaaaaaaaaaa Aaaa Aa Aaaaaaaaaa Aa Aa Aaaaaaaaaaaaaaaaaaaa a Aaaaaaaaaaaaaa Aaaaaaaa Aaaa Aaaa a Aaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaa Aaaa Aaaaaaaaaaaaaaa Aaaaaaaaa Aaaaa Aaaaaa Aaaaaaaaa a Aaaaaaaaaaaaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaa Aaaaa Aaaa Aaa Aaaa Aa Aaaaaaa
a Aaaaaaaaaaaa Aaaa a a Aa Aaaaaaaaaaa Aaaa Aaaa Aaaaaaaaa Aaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaa a Aaaaaaa Aaaaaa Aa Aaaaaaaaaaaaaaaaaaaa Aaaa Aa Aaaa Aaaaaaaaaaa Aaaa Aa Aaaa Aaaa Aaaa Aaaaaaaa Aa a a Aa Aaaaaa Aaaa Aaaa Aaa Aaa a Aaa Aaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaa Aaaaa Aaa Aaaaa Aaaaaaaaaaa Aaa Aaaaa Aa Aaaaaa Aaa a Aa Aaa Aaaaa Aaaaaa
a Aaaa Aaaaaaaaaa Aaaaaaaa Aaaa Aaaaaaaaaaaaa Aaaaaaaaaaa Aa Aaaaa Aaaaaaaaaaaaaaaaaa Aa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaa Aaa Aaa a Aaaa Aaa Aa Aaaaa Aaaa Aaaa Aaaaa Aaa Aa Aaaaaa Aaaaaaa Aa Aaaaa Aaaaaa
🔒Multiple reusable audit directions for cross-process identifier validation under Site Isolation, with concrete IPC entry points to start from.
더 확인하려면 구독해 주세요