[18] WebPaymentCoordinatorProxy_ShowPaymentUI handles arbitrary untyped image data
Severity: Low | Component: WebKit Apple Pay Installments IPC | c945958
관찰 가능한 효과가 사용되지 않는 IPC 필드 제거에 그치기 때문에 Low로 평가됩니다. 실제로 트리거된 버그 사례는 확인되지 않으며, 보안 가치는 순수하게 attack surface 축소에 해당합니다. 구체적인 vulnerability가 표면화되기 전에, 사용되지 않던 base64 → NSData → PassKit 파이프라인이 제거된 것입니다.
Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in
Source/WebCore/Modules/applepay/PaymentInstallmentConfiguration.mm
Patch Details
merchandisingImageData는 WebCoreArgumentCoders.serialization.in에서 [NotSerialized]로 표시되었습니다. 구조체는 [CreateUsing=fromInstallmentConfiguration] factory 방식으로 생성하도록 변경되었습니다. 새로 추가된 ApplePayInstallmentConfigurationWebCore.cpp에서 fromInstallmentConfiguration을 정의하며, 수신 측에서 빈 placeholder 문자열로 구조체를 재구성합니다. PaymentInstallmentConfiguration.mm에서는 WebContent 측의 base64 디코딩 코드가 제거되었습니다. 해당 코드는 NSData로 변환된 값을 [PKPaymentInstallmentConfiguration setMerchandisingImageData:]에 전달하고 다시 읽어오는 round-trip 처리를 담당하던 부분이었습니다. PassKitInstallmentsSPI.h와 AllowedSPI-legacy.toml에서도 관련 SPI 항목이 제거되었습니다. 웹 노출 dictionary 필드는 API 호환성을 위해 no-op 형태로 유지됩니다.
정제되지 않은 비타입 데이터가 sandbox IPC 경계를 넘어 더 이상 해당 입력이 불필요한 권한 있는 image/data sink로 유입되는 구조.
Background
ApplePayInstallmentConfiguration은 Apple Pay 할부 결제 제안을 기술하는 WebIDL dictionary입니다. JS에서 WebContent 내에 생성된 후 결제 sheet를 렌더링하기 위해 UIProcess로 전달됩니다. PassKit(PKPaymentInstallmentConfiguration)은 WebContent보다 높은 권한 수준에서 네이티브 결제 sheet UI를 렌더링합니다. WebKit IPC 직렬화는 WebCoreArgumentCoders.serialization.in을 통해 필드 단위로 처리됩니다. [NotSerialized]는 해당 필드를 wire format에서 제외하며, [CreateUsing=...]은 생성기가 static factory를 통해 구조체를 생성하도록 지시합니다.
Analysis
패치 이전에는 WebContent 접근 권한을 가진 공격자가 임의의 base64 바이트를 전송할 수 있었습니다. UIProcess는 이를 NSData로 디코딩하여 PassKit의 setMerchandisingImageData:에 전달했습니다. commit 메시지에 따르면, 이 필드는 Apple Pay에서 실제로 전혀 소비되지 않은 것으로 확인됩니다.
WebIDL에서 정의된 기능 속성이 IPC를 통해 직렬화되고 UIProcess에서 디코딩되지만 end-to-end로 소비되지 않는 패턴이 있습니다. 이는 반복적으로 등장하는 attack surface에 해당합니다. 특히 데이터가 불투명한 형태(base64 blob, 비타입 NSData, 플랫폼 프레임워크에 전달되는 자유형 문자열)인 경우 위험도가 높아집니다.
한편 이 fix는 WebKit의 serializer generator가 struct layout을 어떻게 제약하는지 보여주는 실제 예시이기도 합니다. 스크립트가 부분 aggregate initializer를 생성할 수 없었기 때문에, C++ struct를 재정렬하는 대신 [CreateUsing=...]을 도입하는 방법을 선택했습니다.