[1] CSP bypass in sandboxed srcdoc iframes
Severity: High | Component: WebCore loader / DocumentWriter | b4390e8
관찰 가능한 영향이 sandboxed srcdoc iframe을 포함하는 모든 문서에서의 script injection / CSP bypass primitive에 해당하며, 분석 신뢰도는 0.92입니다. 기존 WPT 실패 케이스 네 건(location 변경, window.open, form submission 2건)은 commit 수준에서 확인된 근거로, 동일한 단일 조건이 더 넓은 범위의 잘못된 policy 귀속 사례를 유발하고 있었음을 시사합니다.
Source/WebCore/loader/DocumentWriter.cpp
- if (currentHistoryItem && currentHistoryItem->policyContainer()) {
+ if (triggeringAction && triggeringAction->type() == NavigationType::BackForward && currentHistoryItem && currentHistoryItem->policyContainer()) {
const auto& policyContainerFromHistory = currentHistoryItem->policyContainer();
ASSERT(policyContainerFromHistory);
document->inheritPolicyContainerFrom(*policyContainerFromHistory);
LayoutTests/http/tests/security/contentSecurityPolicy/iframe-srcdoc-import-bypass.html
+ iframe1.srcdoc = srcdocContent;
+ iframe2.srcdoc = srcdocContent.replaceAll(iframe1.id, iframe2.id);
+<iframe id="iframe1" sandbox="allow-scripts"></iframe>
+<iframe id="iframe2" sandbox="allow-scripts" srcdoc=""></iframe>
Patch Details
패치 이전의 DocumentWriter::begin()은 현재 HistoryItem에 non-null policy container가 존재하는 경우, 해당 값을 새 문서의 PolicyContainer로 상속했습니다. 이번 수정으로 이 조건이 좁아졌습니다. 이제 history 기반 상속은 triggeringAction이 존재하고 그 NavigationType이 BackForward인 경우에만 동작합니다. 그 외 navigation — sandboxed iframe에 대한 동적 srcdoc 변경 등 — 은 spec이 요구하는 initiator 기반 상속 경로로 처리됩니다. WPT의 inheritance-from-initiator expectation 파일에서 네 건의 결과가 FAIL→PASS로 전환되었습니다(location 변경, window.open, form submission 2건). 새로운 layout test도 추가되었는데, script로 srcdoc를 할당한 뒤 sandboxed iframe이 동적 import()로 cross-origin module을 로드하는 시나리오를 검증합니다.
non-back/forward navigation에서 잘못된 policy container 출처 선택: initiator 상속이 필요한 상황에서 history item 상속이 적용된 패턴.
Background
PolicyContainer는 문서의 CSP, referrer policy, cross-origin policy를 하나로 묶는 WebCore 집합체입니다. HTML 스펙에 따르면 srcdoc 문서는 자체 네트워크 응답이 없으므로, navigation을 유발한 initiator 문서로부터 policy container를 상속해야 합니다. 반면 history traversal의 경우, 문서의 HistoryItem이 원래 policy container의 스냅샷을 보관하여 back/forward 시 동일한 policy로 문서가 복원됩니다. DocumentWriter::begin()은 새 문서 생성 초기 단계에서 실행됩니다. 해당 문서의 스크립트가 실행되기 전 시점에, 어떤 container를 채택할지 결정하는 역할을 담당합니다.
Analysis
패치 이전에는 loader가 단순한 heuristic을 사용했습니다. "history policy container가 존재하면 그것을 사용한다"는 방식이었습니다. back/forward traversal에서는 이것이 spec에 부합하지만, script로 srcdoc를 변경하는 fresh navigation에서는 그렇지 않습니다. iframe에 저장된 history container에는 부모 문서의 CSP가 포함되어 있지 않기 때문입니다. 결과적으로 새 문서는 spec이 요구하는 엄격한 CSP 대신, 허용적이거나 비어 있는 policy를 상속받게 되었습니다.
Aaaaaaaaaa Aaaaa a Aaaaaaaa Aaa Aaaaaa Aaaaaaaa Aaa Aa Aaaaaaa Aaaaaaaaaaaa Aaaaaaa a Aa Aaaaaaaaa Aaaaaaa Aaaaaa a Aaaaaaa Aaaaaaa Aaaaaaaaa Aaaaa Aa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaa Aaaaaa Aa Aaaaa Aa Aaa Aaaaaaaaaaa Aaaaaaa Aaaaa Aaaa Aa Aaa Aaaaaaa Aaaa Aaaaa Aaaaa Aaa a Aa Aaa Aaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaa Aaaa Aaaaaaaaaa Aaaaa Aaa Aa Aaa Aaaaa Aaaaaaaaaa Aaa Aa Aaa Aaa Aaa Aaaaa Aaaa Aaa Aaaaaa
a Aaaaaaaaaaaaaa Aaaaaaaaa Aaaaaaaa Aaaaaaa Aaa Aa Aaa Aaaaaaa Aaaa Aaaaaa Aaaa Aaaa Aaaaaaaaa Aaaa Aa Aa Aaa Aaa Aaaa Aaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaa Aaaaaaa Aaaaaaaaa Aaa a Aa Aaaaaa Aaaa Aaa Aaaa Aaa Aaaa Aa Aa Aaaa Aaa a Aaaaa Aa Aaa Aaa Aaaaa Aaaaaaa Aaaa Aa Aaa Aaa Aaaa
🔒The general mechanics of CSP-inheritance for sandboxed srcdoc iframes are walked through, with attention to which navigation forms previously consulted the wrong policy source and what that meant for an attacker holding only an HTML-injection primitive.
더 확인하려면 구독해 주세요
Audit directions
a Aaaaaaaaaaaa Aaa Aa Aa Aaaaa Aaaaaa Aaaaaaaaa Aaa Aaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaa Aaaaaaa Aaaaaa a Aa Aaa Aaaa Aaaa Aaaaaaaaaaaaa Aaaaa Aaaaaaaaaaa Aaaaaaaaaaaaaa Aaaaaaa Aaaaaaaaaaaaaa Aa Aaaaa Aaaa Aaaa Aaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaa Aaaa Aa Aaaaa
a Aaaa Aaaaa Aaaaaaaaaaaa Aaaa Aa Aaaaaaaaaaaa Aaaaa Aaaaaa a Aaaaaaaaaaaaa a Aaaaaaaaaaaaa Aa Aaa Aaaa Aaaa Aaaaaaaa Aaaaaaa Aaaaaaaaaa Aaaaaaa Aaaaa Aaaaaaa Aaaaaaa Aaaaaaaaa Aaaa Aaaaa Aaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaa a Aaaaaaaaaaaaaaaaaa Aaaaaaa Aaaaa Aaa Aaaaaaaaaaaaaaaaaaaa Aaa Aaaaa Aaa Aaa Aaaaa
a Aaaa Aaaaaaaa Aa Aa Aaa Aa Aaaaa Aaaaaa Aa Aaa Aa Aa Aaa Aaa a Aa Aaaaaaaaaaa Aaaaaaaaaa Aaaaaa Aaaaaaaaaaaaaaaaa Aaaa Aaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa a a Aaaaaaaaaa Aaaa Aaaaa Aaaa Aaaa Aaaaaaaaaaaaaaaaaaaaa a Aaaaaaa Aaaaaaaa Aa a Aaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaa Aaaa
a Aaaaa Aaaaaaaaaa Aaaaa Aaaaaaaa Aaaaaaaaa Aaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaa a Aaaaaaaa Aaaaa Aaaa Aaaa Aaaa Aaaa Aa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaa Aaa Aaaaaaaaaaaaaa Aaaa Aaaaaaaaaaa Aaaaaaaa Aaa Aa Aaaaaaaa Aaaaaaaaaa Aaaa Aa Aaaaaa
🔒Several reusable audit patterns covering policy-container inheritance across multiple loader entry points and local-scheme document constructions, with concrete grep starting points.
더 확인하려면 구독해 주세요