[21] postMessage extends user gesture token lifetime
Medium으로 평가됩니다. diff는
LocalDOMWindow::processPostMessage내UserGestureToken::hasExpired에 존재하던 TOCTOU를 수정합니다. 만료 확인과 gesture 소비 지점이 분리되어 있어, 두 시점 사이에 실제 시간이 경과할 수 있었습니다. 그 결과 1초를 방금 넘긴 token이MessageEventdispatch 중UserGestureIndicator에 설치되는 상황이 가능했고, 이는 popup-blocker bypass로 이어질 수 있는 문제입니다.
두 commit은 동일한 수정을 각기 다른 브랜치에 반영한 것으로, 하나는 다른 쪽의 신속한 backport입니다. processPostMessage에서는 UserGestureIndicator 생성 직전에 userGestureToForward->hasExpired(maximumIntervalForUserGestureForwarding) 검사가 추가되어 재확인하도록 수정되었습니다.
Source/WebCore/page/LocalDOMWindow.cpp
시간 기반 freshness predicate에 대한 TOCTOU: user-gesture 만료 확인 지점과 gesture 소비 지점이 분리되어 있었고, 그 사이에 실제 시간이 경과하는 것이 가능했습니다.
HTML/WebKit 정책상 전달된 gesture는 원래 상호작용으로부터 maximumIntervalForUserGestureForwarding(1초) 이내에서만 유효합니다. 패치 이전에는 검사가 소비 지점을 감싸지 않았기 때문에, 이 제한이 조용히 초과될 수 있었습니다. 이번 패치는 검사를 그대로 중복 추가하는 최소한의 수정입니다. 보다 근본적인 해결책은 해당 검사를 UserGestureIndicator의 constructor 안으로 이동시키는 것입니다.
보안 token의 시간 기반 유효성 조건은 검사 지점과 사용 지점이 분리될 때마다 TOCTOU에 취약합니다. 정당하게 클릭 한 번을 받은 페이지라도 postMessage hop을 연결하면, popup 생성·fullscreen 진입·소리 있는 autoplay 등 gesture-gated API를 정책 window 이후에도 계속 호출할 수 있는 가능성이 있습니다.
이 vulnerability는 사용자 주도 API를 제어하는 user-gesture trust boundary를 약화시킵니다.
Audit directions
UserGestureToken::hasExpired호출 지점과 소비 지점이 멀리 떨어진 경우.Source/WebCore에서hasExpired(UserGestureToken::를 검색하고, 사이에 끼어드는 호출을 점검합니다. fetch keepalive, beacon, navigation API 전달(maximumIntervalForUserGestureForwardingForFetch) 경로에도 동일한 gap이 존재할 수 있습니다.- 비동기 경계를 넘어 전달되는 capability token. MessagePort, BroadcastChannel, ServiceWorker
postMessage에서 유사한 gesture/transient-activation 전달 방식이 있는지 점검합니다. - freshness를 재검증하지 않고 token을 받는 RAII helper.
UserGestureIndicator::UserGestureIndicator(RefPtr<UserGestureToken>, ...)의 constructor에는hasExpired검사가 없습니다. 이번 패치가 국소적으로만 처리하는 구조적 근본 원인에 해당합니다. - 연쇄 postMessage hop. A → B → C 형태로 hop당 0ms 지연을 주었을 때, 임의의 hop 수에 걸쳐 원래
m_startTime을 기준으로 비교하더라도processingUserGesture()가 1초 제한을 넘어 true를 반환하는지 테스트합니다.