← All reports

Generator-enforced `IPC::Untrusted<T>` for origin-bearing UIProcess messages

Component: WebKit IPC | 43379f4

WebKit은 작업을 sandbox 안의 WebContent process와 권한을 가진 UIProcess로 나눠 처리합니다. 두 process 사이의 message는 .messages.in 파일에 선언되고, generate-message-receiver.py가 이를 C++ 코드로 변환합니다. 이때 SecurityOriginDataClientOrigin처럼 origin을 담는 타입은 UIProcess에서 보안과 직결된 판단에 쓰이는데, 권한 부여, geolocation, WebAuthn, site isolation이 여기에 해당합니다. 그런데 그동안은 WebContent process가 주장하는 origin을 그대로 받아들였습니다. WebKit의 threat model에서 장악된 renderer는 attacker가 통제하는 신뢰할 수 없는 구성 요소입니다. 따라서 renderer가 보고하는 origin은 UIProcess가 그 값을 근거로 동작하기 전에 실제 사실과 대조해 확인되어야 합니다.

IPC hardening 시리즈의 세 번째에 해당하는 commit으로, generator와 build system 쪽 지원이 추가되었습니다. untrusted_origins.py, generator 단의 강제 검사, header 및 타입 배선이 여기에 포함됩니다. 이제 message receiver generator는 WebContent에서 출발한 message에서 SecurityOriginData, ClientOrigin, RegistrableDomain, Site, SecurityOrigin을 그대로 받는 UIProcess handler를 만나면 컴파일 자체를 거부합니다. 해당 parameter는 반드시 IPC::Untrusted<T>로 감싸야 합니다. 기존 호출 지점 37곳은 모두 wrapping되었습니다.

wrapping된 37곳은 여전히 모두 unsafeExtractWithoutValidation(NeedsReview)를 호출하므로, 런타임에서 실제로 검증되는 값은 아직 없습니다. 다만 검증되지 않은 origin 경로 전체를 타입 시스템에서 열거할 수 있게 되었다는 점이 이번 변경의 성과입니다. 시리즈의 이후 commit에서는 이 호출 지점들이 지정된 검증 절차(IPC::IsValidationProcedureFor specialization)로 대체되어, 값을 사용하기 전에 검증을 거치게 됩니다.

앞으로 눈여겨볼 패턴은, 하나의 process 경계에서 특정 타입들을 compiler가 강제로 막는 deny-list 방식입니다. Narrow: NeedsReview가 붙은 37곳의 추출 지점은, 지금 renderer가 주장한 origin을 그대로 신뢰하는 UIProcess handler 전부를 공개된 작업 목록으로 만들어 둔 셈입니다. 각 handler가 그 값을 가지고 무엇을 하는지 지금 읽어볼 가치가 있으며, 그중에서도 권한 판단이나 storage 결정으로 이어지는 쪽이 흥미로운 절반입니다. Wider: 강제 검사는 이름이 지정된 다섯 개 타입을 기준으로 동작합니다. 그래서 origin이 struct 안에 들어 있거나, URL 안에 담겨 있거나, 문자열 필드 형태로 UIProcess에 도달하는 경우에는 generator를 그대로 통과합니다. .messages.in 선언을 훑어보며, 자기 자신은 origin 타입이 아니면서 내부적으로 origin을 실어 나르는 parameter 타입을 찾아볼 필요가 있습니다. Widest: 같은 신뢰 문제는 WebContent에서 권한 있는 process로 향하는 모든 경로에 똑같이 적용되지만, 이번 commit이 다루는 범위는 UIProcess 방향뿐입니다. Networking process 역시 WebContent로부터 origin을 담은 message를 받는데, 그 경로는 이번 generator 변경이 막아주지 않습니다. 검토 시 신호가 되는 지점은 타입 이름이 DataDomain으로 끝나면서 wrapping되지 않은 message handler parameter입니다.