Response sanitization no longer gated by a renderer-supplied IPC flag
The renderer got a vote on whether its own responses were sanitized.
Component: WebKit NetworkProcess | c5fabb4
WebKit의 multi-process 아키텍처에서는 NetworkProcess 입장에서 WebContent process를 신뢰하지 않는 대상으로 취급합니다. JS 엔진 버그 등을 통해 renderer가 compromise되더라도, 그 피해는 NetworkProcess 경계 안에서 봉쇄되어야 한다는 전제입니다. 다만 이 봉쇄가 성립하려면, WebContent로부터 도착하는 IPC parameter가 그 자체만으로 security-relevant한 동작을 좌우해서는 안 됩니다. NetworkResourceLoadParameters는 WebContent가 원하는 load를 기술하기 위해 보내는 구조체인데, 그 필드 중 하나인 shouldRestrictHTTPResponseAccess가 문제였습니다. 이 boolean 값은 아무 검증 없이 그대로 전달되어, response가 renderer에게 반환되기 전에 sanitize할지 여부를 결정하고 있었습니다.
이번 commit은 해당 필드를 제거합니다. Set-Cookie 제거와 cross-origin header filtering으로 구성되는 response sanitization은 이제 NetworkResourceLoader::sanitizeResponseIfPossible에서 클라이언트가 넘긴 값에 좌우되지 않고 무조건 수행됩니다. 이 flag는 원래 WK1이 sanitization을 opt-out할 수 있도록 남겨둔, WK1/WK2 공존 시절의 legacy 잔재였습니다. WK1이 제거된 이후로는 정상적인 클라이언트라면 사실상 항상 true였지만, 그 체크는 하드코딩되지 않고 여전히 IPC로 제어되는 상태로 남아 있었습니다.
Significance
Compromise된 WebContent process가 이 flag를 clear시키면 response header sanitization을 통째로 무력화할 수 있고, 결과적으로 Set-Cookie를 비롯한 cross-origin에 민감한 header가 renderer에게 노출될 수 있습니다. 이는 NetworkResourceLoadParameters를 위조하거나 조작할 수 있는 프로세스라면 누구나 도달 가능한 잠재적 bypass 경로이며, second-stage renderer exploit이 정확히 이런 위치에 놓이게 됩니다. 이 필드를 제거함으로써, IPC로 제어되던 정책 결정이 compile-time 결정으로 바뀌게 됩니다. Hostile한 sender를 상대로도 안전하게 살아남는 형태는 사실상 이것뿐입니다.
Audit directions
여기서 찾아야 할 패턴은 IPC 경계를 거슬러 올라오는 정책성 boolean입니다. 좁게 보면, NetworkResourceLoadParameters와 그 sibling에 해당하는 load-parameter 구조체들을 훑어, 값 하나로 검증 경로와 비검증 경로를 가르는 필드가 남아 있는지 확인해야 합니다. 알아볼 수 있는 단서는 sanitization, validation, filtering 호출 주변에서 if (params.shouldX) 형태로만 소비되는 필드입니다. 조금 더 넓게 보면, 이런 구조는 낮은 권한의 프로세스가 높은 권한의 프로세스에게 작업을 기술하는 모든 지점에서 동일하게 나타날 수 있습니다. 그래서 GPUProcess와 UI-process의 parameter 구조체들도 같은 방식으로 점검할 필요가 있는데, 여기서의 단서는 데이터가 아니라 permission이나 restriction의 이름을 딴 bool 또는 enum 필드입니다. 가장 넓게 보면, legacy 호환성 flag 전반이 이 클래스의 가장 수확이 큰 사례에 해당합니다. "실제로는 항상 true"라는 상태가 강제할 필요성 자체를 지워버리기 때문입니다. false 값을 만들어내던 마지막 클라이언트(WK1, deprecated SPI, test 전용 harness 등)가 제거된 필드를 검색하고, 각각이 단순히 방치된 것이 아니라 실제로 하드코딩되었는지 확인해야 합니다.