← All reports

Check iframe navigations for Local Network Access against their initiator

Local Network Access checked the fetches, but not the iframe pointed at localhost.

Component: WebKit NetworkProcess Local Network Access | c62d29d

LayoutTests/http/wpt/fetch/local-network-access/navigating-a-frame-is-checked-against-the-initiator-expected.txt

+PASS a non-secure local initiator cannot navigate a frame to loopback
+PASS a secure local initiator needs permission to navigate a frame to loopback
+PASS a non-secure public initiator cannot navigate a frame to loopback
+PASS a loopback initiator can navigate a frame to loopback without permission
+PASS a secure public initiator needs permission to navigate a frame to loopback
+PASS a secure public initiator with permission can navigate a frame to loopback

Local Network Access(LNA)는 WICG spec입니다. 더 공개된 address space에서 덜 공개된 address space로 향하는 요청을 제한합니다. 공개 정도는 public, local, loopback 순으로 낮아집니다. 이런 요청이 허용되려면 secure context와 permissions-policy 허가가 모두 필요합니다.

subresource load라면 network process는 요청을 보낸 document 자신의 address space를 기준으로 판단합니다. 반면 navigation은 사정이 다릅니다. navigation의 client는 이동 대상 frame이 아니라, navigation을 시작한 initiator document이기 때문입니다.

WebKit은 initiator 정보를 NavigationRequester에 담아 network process로 전달합니다. 이 값은 web process에서 IPC로 serialize되어 넘어옵니다. 또한 이 설계에서는 해당 load가 top-level인지 여부도 web process가 알려주는 값입니다.

NetworkResourceLoader가 더 이상 iframe main-resource load에 대해 LNA check를 건너뛰지 않도록 수정되었습니다. 먼저 NavigationRequester에는 기존 address space 외에 새로운 값들이 추가되었습니다. initiator의 secure-context flag, 그리고 local-network 및 loopback-network permissions-policy 상태입니다. iframe navigation에 대한 check는 이 값들과 initiator의 origin을 기준으로 수행됩니다.

한편 initiator가 없는 navigation도 더 이상 건너뛰지 않습니다. 대신 non-secure public client로 간주해 판단합니다. top-level navigation은 기존과 같이 예외로 유지되었습니다.

Before:                                  After:
WebContent (public page)                 WebContent (initiator)
  └─► iframe nav -> 127.0.0.1              └─► iframe nav -> 127.0.0.1
        │                                        │ NavigationRequester{addrSpace,
        ▼                                        │   isSecureContext, LNA/loopback PP}
NetworkResourceLoader                            ▼
  main resource? ──► skip LNA            NetworkResourceLoader::checkLocalNetworkAccess
        │                                  top-level? ──► exempt
        ▼                                  iframe?     ──► check vs initiator
   load proceeds unchecked                 no initiator? ─► non-secure public
                                                │
                                                ▼ allow / deny

이전에는 public 페이지가 non-secure context에서도 LNA check 없이 iframe을 loopback 또는 local 주소로 navigate할 수 있었습니다. web에서 intranet과 localhost로 향하는 요청을 막으려는 기능에 보호 공백이 있었던 셈입니다.

이번 변경은 security boundary check를 수정합니다. 동시에 NavigationRequester에 IPC로 serialize되는 새 필드가 추가되었습니다. secure-context flag 하나와 permissions-policy bit 두 개입니다.

commit에 따르면 top-level 여부 판단과 initiator 필드는 여전히 web process에서 전달됩니다. 따라서 WebContent process가 compromise된 경우를 가정할 수 있습니다. 이 경우 공격자가 이 check의 입력값을 제어할 가능성이 있습니다.

좁은 범위에서는 NavigationRequester::from을 생성하는 code path를 점검할 필요가 있습니다. initiator가 설정되지 않은 채 남는 경로가 있는지 확인해야 합니다. initiator를 잘못 귀속하거나, 엉뚱한 document를 선택하는 경로도 마찬가지입니다. 참고로 commit은 history traversal과 reload를 special case로 명시하고 있습니다. 이 두 경우는 frame 자신의 document를 기준으로 판단합니다.

범위를 넓히면, iframe 경로를 우회하는 navigation 유형이 점검 대상입니다. redirect, form submission, window.open, target 이름을 지정한 navigation, srcdoc/about:blank 등이 여기에 해당합니다. cross-process navigation이나 site-isolation navigation도 살펴볼 필요가 있습니다. 이 과정에서 requester 데이터가 유실되거나 기본값으로 채워질 가능성이 있기 때문입니다.

이 밖에도 확인할 지점이 몇 가지 있습니다. 먼저 public 주소에서 local 주소로 이어지는 redirect chain이 같은 initiator 기준으로 다시 check되는지 봐야 합니다. 또한 새 필드의 false 기본값이 모든 사용 지점에서 fail-closed로 동작하는지도 점검 대상입니다. 마지막으로, 실제로는 subframe load인 요청이 top-level 예외 경로에 도달할 수 있는지 확인할 필요가 있습니다.