← All reports

Enable storage site validation

Component: WebKit NetworkProcess storage | df8786e

Source/WebKit/NetworkProcess/storage/NetworkStorageManager.cpp

+#define STORAGE_MESSAGE_CHECK(assertion, connection) do { \
+ if (!(assertion)) [[unlikely]] { \
+ RELEASE_LOG_FAULT(Storage, "%s: storage site validation failed", WTF_PRETTY_FUNCTION); \
+ return; \
+ } \
+} while (0)
+#define STORAGE_MESSAGE_CHECK_COMPLETION(assertion, connection, completion) do { \
+ if (!(assertion)) [[unlikely]] { \
+ RELEASE_LOG_FAULT(Storage, "%s: storage site validation failed", WTF_PRETTY_FUNCTION); \
+ return completion; \
+ } \
+} while (0)
 
void NetworkStorageManager::persisted(IPC::Connection& connection, const WebCore::ClientOrigin& origin, CompletionHandler<void(bool)>&& completionHandler)
{
assertIsCurrent(workQueue());
- MESSAGE_CHECK_COMPLETION(isSiteAllowedForConnection(connection.uniqueID(), WebCore::RegistrableDomain { origin.topOrigin }), connection, completionHandler(false));
+ STORAGE_MESSAGE_CHECK_COMPLETION(isSiteAllowedForConnection(connection.uniqueID(), WebCore::RegistrableDomain { origin.topOrigin }), connection, completionHandler(false));
...

WebKit은 웹 콘텐츠를 sandbox로 격리된, 신뢰도가 낮은 WebContent process에서 실행합니다. 반면 localStorage, IndexedDB, Cache API, FileSystem API 같은 storage는 더 권한이 높은 NetworkProcess에 위치하며, IPC를 통해 접근됩니다. MESSAGE_CHECK는 WebKit의 표준 IPC sanity-check 패턴으로, assertion이 실패하면 발신자가 손상되었거나 버그가 있다고 간주하고 connection을 즉시 종료합니다. 이는 hard security boundary 역할을 합니다.

이번 commit은 WebsiteDataStore::m_storageSiteValidationEnabled를 기본값으로 활성화합니다. 이에 따라 NetworkStorageManager는 들어오는 IPC 메시지에 대해 origin/site를 검증하게 됩니다. 또한 STORAGE_MESSAGE_CHECK가 새로 도입되어, 약 20개의 storage IPC handler에서 기존 MESSAGE_CHECK를 대체합니다. 이 새 매크로는 의도적으로 약화된 variant입니다. 실패 시 RELEASE_LOG_FAULT를 통해 fault를 기록하고 조기 반환하되, connection은 유지됩니다. 이렇게 해두면 WebKit은 이 check들을 전체 MESSAGE_CHECK로 승격시키기 전에, 필드에서 false-positive 비율을 먼저 관찰할 수 있습니다. FIXME가 남아있는 이유이기도 합니다.

site-isolation boundary가 production에 실제로 적용됩니다. NetworkProcess는 이제 요청을 처리하기 전에, 해당 WebContent process가 특정 site의 storage에 접근할 권한이 있는지 능동적으로 확인합니다. 이로써 손상된 renderer가 다른 origin의 storage 데이터를 읽거나 쓸 수 있었던 gap이 막힙니다. 다만 현재는 의도적으로 connection 종료 대신 soft failure 방식을 택한 상태입니다.

전방위적으로 나타나는 패턴은, security-enforcing 경로에서 hard-fail check가 soft-fail check로 대체되었다는 점입니다. 이때 조기 반환이 남기는 상태는, 원래 connection-kill 경로였다면 결코 만들어지지 않았을 상태입니다. 좁게 보면, 전환된 약 20개 handler 전반에서 MESSAGE_CHECKSTORAGE_MESSAGE_CHECK가 관련된 state에 섞여 쓰이는 경우를 살펴볼 필요가 있습니다. 특히 어떤 함수의 soft-fail 반환이 일부 상태 변경 이후, 그에 대응하는 cleanup보다 앞서 발생하는 경우, 또는 completion handler가 기본값과 함께 호출되어 이후 caller가 이를 정상 데이터로 취급하는 경우가 의심 지점입니다. 넓게 보면, 같은 형태의 문제가 WebKit IPC handler가 늦게 검증을 수행하는 곳이면 어디든 존재할 수 있습니다. 다른 NetworkProcess message receiver에서도, check가 함수 진입 지점이 아니라 object lookup이나 map insertion 이후에 배치된 경우를 점검할 필요가 있습니다. side effect 이후에 실행되는 check는 최종 연산만 막을 뿐, 그 이전에 발생한 상태 변경 자체는 막지 못하기 때문입니다. 가장 넓게 보면, 여기서 다루는 일반적인 문제 유형은 여러 handler에 등장한다는 이유만으로 커버리지가 완전하다고 가정되는 validation predicate입니다. isSiteAllowedForConnection/canConnectionAccessSiteForWebStorage가 실행되기 이전에 도달 가능한 진입점들을 나열해볼 필요가 있습니다. connection 설정, session 등록, 그리고 이전에 등록된 식별자로부터 origin을 resolve하는 모든 handler가 여기에 해당합니다. 이런 경로들이 바로 이후 check가 참조하게 될 상태를 미리 만들어두는 지점이기 때문입니다.