[7] IndexedDB Connection/Transaction Identifier Confusion
Broker 측 IDB registry가 renderer로부터 제공받은 identifier를 sender에 재바인딩하지 않고 직접 역참조하는 문제를 수정하기 때문에 High로 평가됩니다. 확보 가능한 primitive는 cross-renderer(사실상 cross-origin) 수준의 IndexedDB 레코드 읽기, 쓰기, 삭제입니다.
NetworkStorageManager의 IDB IPC handler는 IDBStorageRegistry를 통해 handle만으로 IDBDatabaseConnectionIdentifier/IDBResourceIdentifier를 조회했습니다. 이 구조에서는 임의의 WebContent process가 다른 renderer의 identifier를 제출하여, NetworkProcess가 해당 요청을 그대로 처리하도록 만들 수 있었습니다.
Source/WebKit/NetworkProcess/storage/IDBStorageRegistry.cpp
Patch Details
connection()과 transaction()이 이제 IPC::Connection&을 인자로 받아 isValidConnectionForIPC()를 호출합니다. 이 함수는 database connection의 소유 client를 확인하고, ipcConnection()과 sender의 uniqueID()를 비교합니다. establishTransaction, commitTransaction, putOrAdd, getRecord, openCursor, iterateCursor 등 모든 IDB IPC handler가 IPC::Connection&을 전달받도록 수정되었습니다.
IPC trust boundary에서 broker가 발급한 opaque identifier를 역참조할 때, originating IPC connection의 소유권 검증이 누락된 sender-resource 바인딩 패턴.
Background
IndexedDB는 renderer 측의 WebCore layer와 NetworkProcess broker로 분리되며, IDBStorageRegistry가 이 사이의 상태를 관리합니다. Registry가 보유하는 자료구조는 세 가지입니다. m_connectionsToClient는 IDBConnectionIdentifier를 key로 하며 originating IPC::Connection::UniqueID를 value로 기록하고, m_connections는 IDBDatabaseConnectionIdentifier를 key로, m_transactions는 IDBResourceIdentifier를 key로 삼습니다. IDBResourceIdentifier::connectionIdentifier()는 client connection으로의 역참조 링크를 제공하며, 검증에 실패하면 MESSAGE_CHECK가 해당 child process를 종료합니다.
Analysis
Renderer에 전달된 identifier는 capability입니다. 따라서 broker는 매 호출마다 이를 재바인딩해야 합니다. 패치 이전에는 WebContent A가 WebContent B의 identifier를 담아 establishTransaction / putOrAdd / getRecord를 전송하면, NetworkProcess가 B의 connection을 대상으로 해당 요청을 그대로 처리하는 구조였습니다.
Read 경로(getRecord, getAllRecords, getCount, openCursor, iterateCursor)는 요청에 포함된 connection-to-client identifier를 통해 B의 레코드를 A로 유출합니다. Write 경로(putOrAdd, deleteRecord, clearObjectStore, deleteObjectStore)는 B의 데이터베이스를 손상시키며, version change handler(didFireVersionChangeEvent, abortOpenAndUpgradeNeeded)는 B의 upgrade lifecycle을 교란하는 수단이 됩니다.
이 취약점의 primitive는 메모리 안전성 문제가 아닌, 논리적 수준의 이슈입니다. Registry가 WeakPtr을 보유하고 조회된 객체의 타입도 명확한 만큼, UAF나 type confusion이 발생할 여지는 없습니다. 영향은 기밀성과 무결성 계층에 국한됩니다. 한편, 이번 commit이 check를 lookup choke-point 안으로 의도적으로 내린 데는 이유가 있습니다. "새로운 IPC를 도입할 때 MESSAGE_CHECK를 빠뜨리지 않도록" 하려는 명시적 의도가 담긴 설계 결정이기 때문입니다.
이 취약점은 WebContent 간 IndexedDB 상태를 격리하는 IPC trust boundary를 약화시킵니다. storage layer 수준에서 same-origin 정책 및 origin partitioning을 우회할 수 있는 취약점입니다.
Audit directions
- 소유권을 재검증하지 않는 broker 측 identifier-to-resource registry.
CacheStorageRegistry,FileSystemStorageHandleRegistry,StorageAreaRegistry,ServiceWorkerStorageManager및Source/WebKit/NetworkProcess/storage/하위의 모든*Registry/*Manager를 점검합니다.get()/find()경로의 시그니처에IPC::Connection&이 누락된 경우를 확인해야 합니다. MESSAGE_CHECK없이 registry를 통해 identifier를 역참조하는 IPC handler.Source/WebKit/NetworkProcess와Source/WebKit/GPUProcess에서IPC::Connection&과 identifier를 함께 받는 handler 메서드를 검색합니다. GPUProcess의RemoteDisplayList,RemoteRenderingBackend,RemoteWebGLresource identifier부터 시작하는 것이 좋습니다.connectionIdentifier()/출처를 노출하는 identifier 타입.IDBResourceIdentifier,WebTransportSessionIdentifier,WebPushIdentifier의 호출 지점을 점검하고, liveIPC::Connection&확인 없이 출처를 읽는 경우를 찾아야 합니다.- work queue 내부의 TOCTOU. Connection A에 대한 registry 조회가 성공한 이후, A가 연결을 끊고
UniqueID가 재사용된 시점에 대기 중인 continuation이 그 결과를 재사용한다면, 이후 작업이 잘못 귀속될 가능성이 있습니다.IPC::Connection::UniqueID의 lifetime/uniqueness 계약을 검증해야 합니다.