[1] WebAuthn UIProcess origin spoofing via unvalidated IPC fields
Severity: High | Component: WebKit UIProcess WebAuthentication | 315ac30
diff는 WebContent-to-UIProcess 경계에서 발생하는 검증 누락 지점을 제거합니다. 이 취약점은 장악된 renderer가 임의의 relying-party origin에 WebAuthn ceremony를 연결할 수 있게 했으며, cross-site credential 위장까지 이어지려면 사전 renderer 장악만 있으면 됩니다. 이는 상정된 위협 모델에 해당합니다. 다만 이 취약점 자체에 memory corruption primitive는 없습니다.
WebContent process가 장악된 경우, WebAuthn MakeCredential/GetAssertion IPC 메시지를 UI process로 전송할 때 FrameInfoData의 securityOrigin이나 parentOrigin 파라미터를 위조할 수 있습니다. 이를 통해 공격자 페이지는 다른 origin(예: 은행)을 사칭하여 credential을 생성하거나 assertion을 요청할 수 있습니다. 이번 patch는 이를 차단하기 위해 MESSAGE_CHECK를 추가했습니다.
Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp
-void WebAuthenticatorCoordinatorProxy::getAssertion(FrameIdentifier frameId, FrameInfoData&& frameInfo, ... std::optional<WebCore::SecurityOriginData> parentOrigin, RequestCompletionHandler&& handler)
+void WebAuthenticatorCoordinatorProxy::getAssertion(IPC::Connection& connection, FrameIdentifier frameId, FrameInfoData&& frameInfo, ... std::optional<WebCore::SecurityOriginData> parentOrigin, RequestCompletionHandler&& handler)
{
RefPtr webPageProxy = m_webPageProxy.get();
...
+ RefPtr frame = WebFrameProxy::webFrame(frameId);
+ if (!frame) {
+ RELEASE_LOG_ERROR(WebAuthn, "Frame not found for WebAuthn GetAssertion request");
+ return handler({ }, static_cast<AuthenticatorAttachment>(0), ExceptionData { ExceptionCode::InvalidStateError });
+ }
+ if (frame->url().protocolIsInHTTPFamily()) {
+ auto expectedOrigin = SecurityOriginData::fromURLWithoutStrictOpaqueness(frame->url());
+ MESSAGE_CHECK_COMPLETION_BASE(frameInfo.securityOrigin == expectedOrigin, connection,
+ handler({ }, static_cast<AuthenticatorAttachment>(0), ExceptionData { ExceptionCode::InvalidStateError }));
+ }
+ if (parentOrigin) {
+ bool foundMatchingAncestor = false;
+ bool hasHTTPAncestor = false;
+ for (RefPtr ancestor = frame->parentFrame(); ancestor; ancestor = ancestor->parentFrame()) {
+ if (!ancestor->url().protocolIsInHTTPFamily())
+ continue;
+ hasHTTPAncestor = true;
+ auto ancestorOrigin = SecurityOriginData::fromURLWithoutStrictOpaqueness(ancestor->url());
+ if (*parentOrigin == ancestorOrigin) { foundMatchingAncestor = true; break; }
+ }
+ if (hasHTTPAncestor)
+ MESSAGE_CHECK_COMPLETION_BASE(foundMatchingAncestor, connection, handler(...));
+ }
handleRequest({ ..., WTF::move(frameInfo), ..., parentOrigin }, WTF::move(handler));
}
LayoutTests/http/tests/ipc/web-authenticator-get-assertion-spoofed-origin-crash.html
+const spoofedOrigin = { data: { variantType: 'WebCore::SecurityOriginData::Tuple', variant: { protocol: 'https', host: 'evil.com', port: {} } } };
+CoreIPC.UI.WebAuthenticatorCoordinatorProxy.GetAssertion(IPC.webPageProxyID, { frameInfo: { ... securityOrigin: spoofedOrigin, topOrigin: spoofedOrigin, ... }, options: { ... }, mediation: 0, parentOrigin: {} });
Patch Details
이제 makeCredential과 getAssertion 모두 첫 번째 파라미터로 IPC::Connection&를 받습니다. 이를 통해 수신 측에서 connection을 종료하는 check를 수행할 수 있습니다. 각 handler는 WebFrameProxy::webFrame(frameId)를 통해 실제 frame을 조회하고, frame이 존재하지 않으면 InvalidStateError를 반환하며 처리를 중단합니다. frame URL이 HTTP(S)인 경우에는 SecurityOriginData::fromURLWithoutStrictOpaqueness(frame->url())로 예상 origin을 다시 계산하고, MESSAGE_CHECK_COMPLETION_BASE를 통해 frameInfo.securityOrigin == expectedOrigin을 검증합니다. getAssertion은 추가로 frame->parentFrame()을 순회하며, HTTP(S) ancestor가 존재하는 경우 parentOrigin이 해당 ancestor origin 중 하나와 일치해야 한다는 조건을 부여합니다. IPC 테스트용 layout test 두 개는 위조된 origin으로 요청을 전송하고 WebContent process가 종료되는 것을 확인합니다.
신뢰할 수 없는 WebContent process에서 전달된 security origin을 UI process가 소유한 frame 상태와 재검증하지 않고 그대로 신뢰하는 패턴.
Background
WebKit은 샌드박스 환경의 WebContent(renderer) process와 권한이 있는 UI process 사이에서 작업을 분리합니다. 보안에 민감한 동작은 IPC 메시지로 이 경계를 넘게 되며, UI process는 모든 필드를 공격자가 제어 가능한 것으로 간주해야 합니다. MESSAGE_CHECK/MESSAGE_CHECK_COMPLETION_BASE 매크로는 조건이 실패하면 해당 IPC connection을 종료합니다. 즉, WebContent process 자체를 종료시키는 것으로, regression test 이름이 *-crash인 이유가 여기에 있습니다. FrameInfoData.securityOrigin은 renderer가 frame의 origin에 대해 주장하는 값입니다. 반면 WebFrameProxy::webFrame(frameId)는 UI process가 직접 관리하는 frame 정보를 반환하며, 여기서의 url()이 신뢰할 수 있는 기준이 됩니다. WebAuthn MakeCredential/GetAssertion은 relying-party origin 범위에서 credential ceremony를 수행합니다. cross-origin(iframe) assertion의 경우 parentOrigin이 embedder를 나타내며, 실제 ancestor frame의 origin과 일치해야 합니다.
Analysis
이번 취약점은 origin spoofing / authority confusion에 해당하며, memory corruption과는 관계가 없습니다. patch 이전에는 UI process의 WebAuthn 수신 측이 IPC 메시지에서 frameInfo.securityOrigin과 parentOrigin 인수를 그대로 받아, 신뢰할 수 있는 frame 상태와 비교하는 과정 없이 handleRequest/buildClientDataJson으로 전달했습니다. WebKit의 IPC 신뢰 모델에서 renderer는 신뢰할 수 없는 대상입니다. renderer가 직렬화하는 모든 필드는 UI process가 소유한 정보를 기준으로 재검증되어야 하는데, 이 단계가 단순히 빠져 있었습니다.
Aaa Aaaaaaaaaa Aaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaa Aaaaaaaaaaaaaaaaaaaa Aaaaa Aa a Aaaaa Aa Aa Aaaaaa Aa Aa Aaaaaa Aaaaa Aaaa Aa Aaaaaaaa a Aaa Aaa Aaaaa Aaaa Aaaaaaaaaaaaaaaa Aaaaaa Aaa Aaaaaaaaaaaaa Aaaaaaaa Aaa Aaaaaaaa Aaaaaaaa Aaa Aaa Aaaaaa Aaa Aaaaaaaa Aaaaaaaaaaaa Aaaaa Aaaaaaaaaaaaaaaa Aaaa Aaa Aaaaaaaaa Aaa a Aaaaa Aa Aaaa Aaa a Aa Aaaaaaaaaa Aaaaaaaa Aaaaaaaaaaaaaaa Aaaaaaa Aaa Aaaaaa Aaaaaa Aaaaaaaaaa Aaaaaaaaaaa Aaaa Aaaa Aa Aaaaaaaa Aaa Aaaaaa Aaa Aaaaaaa Aaaaaaaaaaaaaaaaaaaaaa Aaaaaa Aaa Aaaa Aaa Aaa Aaa Aaaaaa Aaaaaaaaaaaaa Aaaaaaaa Aaa Aa Aaa Aaaaaaaaaaaaaaaa Aaaa Aaaa Aaaa Aaa Aaaaa
a Aaaa Aaaaaaaa Aaaaaa Aaaaaaaa Aa Aaaaaaaaaaaaaaaaaaaaaaa Aa Aaa Aaaaaaa Aaaaaaaaa Aa Aaa Aa Aaa Aaaa Aa Aaaaaaaaaaaaaa Aaaa Aaaaaaaaaaaaa Aaaaaaa Aa Aa Aaaaaa Aaaaaaa Aaaaa Aa Aa Aaaaaa Aaaaaaaaa Aaa Aaaa Aaa Aa Aaa Aaaaaaaa Aaaaaaaaaa Aa Aa Aaaaaaaaaa Aaaa Aaaaaaaa Aaaaaaaaaaaaaa Aa Aaaa Aaa a Aaaaa Aaaaaa Aa Aaaaaaaa Aaa Aaaaaaaaaaaaaaa Aaaa Aaaaaaa Aa Aaaa Aaaaaaaaaaaaaaaa Aa Aaaaaaaaa Aaa Aaaaaa Aa Aaaaaaaaaa Aaaaaa Aaaaaaaaaaaa Aa Aa Aa Aaa Aaaaaaa Aaaa Aaa Aaa Aaaaaa
🔒Examines how a renderer-supplied identity field crosses into a privileged process and what an attacker can claim before the boundary is enforced.
더 확인하려면 구독해 주세요
Audit directions
a Aaaa Aa Aaaaaaa Aaaaaaaaa Aaaaaa Aaa Aaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaa Aaa Aa a a Aaaaaaaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaaaaaa Aa Aaaaa Aaaa Aaaaa Aa Aaa Aaaa Aaa Aaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaa Aaaaa Aa Aa Aa Aa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaa Aaaaaa Aaaaaa Aaaaaaaaa Aaa Aaa Aaaa Aaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaa Aaaaa Aaaaaaaaaaaaaaa Aa Aaaaaaaaaaa Aaa Aaa Aaaa Aaa Aaaaaa
a Aaaa Aa Aaa Aaaaaaaa Aaaaa Aaaaaaaaaaaaaaaa Aaaa Aaaaaaaaaaaa Aaaaaaaa Aaaaa a Aaa Aaaaaaaaa Aa a Aaaa Aaaaa Aaa Aaaaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaa Aaaaaaaa Aa Aaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaa Aaaaaaaaaaaa Aaaa a Aaa a Aaa Aaaaaa Aaa Aaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaa Aaa Aa Aa Aaaa Aa Aaa a Aaa Aaaa a Aaaaa
a Aaaaaa Aa Aa Aaaaaaaaaaa Aa Aaaaaaa Aaaa Aa Aaaaaaaa Aa Aaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaa Aaa Aa Aaaa Aa Aaaaaa Aaaa Aa Aaaaaaa Aaaaa Aaaaaa a Aaaaa Aaaaaaa Aa Aaa Aaaaa Aaa Aaa Aaaaa Aaa Aaaaaa
🔒Multiple reusable audit patterns identified for IPC origin-validation gaps, with concrete UIProcess starting points for variant discovery.
더 확인하려면 구독해 주세요