비공개 네트워크 액세스: 프리플라이트 도입

Titouan Rigoudy
Titouan Rigoudy
Yifan Luo
Yifan Luo

업데이트

  • 2022년 7월 7일: 현재 상태가 업데이트되고 IP 주소 공간 정의가 추가되었습니다.
  • 2022년 4월 27일: 타임라인 공지가 업데이트되었습니다.
  • 2022년 3월 7일: Chrome 98에서 문제가 발견된 후 롤백이 발표되었습니다.

소개

Chrome에서는 비공개 네트워크 액세스 (PNA) 사양의 일부로 공개 웹사이트에서 비공개 네트워크 엔드포인트에 직접 액세스하는 기능이 지원 중단됩니다.

Chrome은 대상 서버에 명시적 권한을 요청하는 하위 리소스의 비공개 네트워크 요청보다 먼저 CORS 프리플라이트 요청을 전송하기 시작합니다. 이 실행 전 요청은 새 헤더 Access-Control-Request-Private-Network: true를 전달하며 이에 대한 응답은 상응하는 헤더 Access-Control-Allow-Private-Network: true를 포함해야 합니다.

목표는 비공개 네트워크의 라우터 및 기타 기기를 대상으로 하는 교차 사이트 요청 위조 (CSRF) 공격으로부터 사용자를 보호하는 것입니다. 이러한 공격으로 수십만 명의 사용자가 영향을 받았으며 공격자가 사용자를 악성 서버로 리디렉션할 수 있습니다.

출시 계획

Chrome은 웹사이트에서 변경사항을 감지하고 그에 따라 조정할 시간을 주기 위해 두 단계로 이 변경사항을 출시할 예정입니다.

  1. Chrome 104:

    • Chrome 실험: 비공개 네트워크 하위 리소스 요청보다 실행 전 요청을 먼저 전송합니다.
    • 프리플라이트 실패는 DevTools에만 경고를 표시하며, 그 외의 비공개 네트워크 요청에는 영향을 미치지 않습니다.
    • Chrome은 호환성 데이터를 수집하여 영향을 받는 최대 규모의 웹사이트에 연락합니다.
    • 기존 웹사이트와 폭넓게 호환될 것으로 예상됩니다.
  2. 빠르면 Chrome 113에서는 다음 사항이 적용됩니다.

    • 이는 호환성 데이터를 통해 변경사항이 충분히 안전하다고 표시되고 필요한 경우 Google에서 직접 연락한 경우에만 시작됩니다.
    • Chrome은 프리플라이트 요청이 성공하고 그렇지 않으면 요청이 실패하도록 합니다.
    • 이 단계의 영향을 받는 웹사이트에서 시간 연장을 요청할 수 있도록 지원 중단 체험판이 동시에 시작됩니다. 무료 체험은 최소 6개월 동안 지속됩니다.

비공개 네트워크 액세스 (PNA)란 무엇인가요?

비공개 네트워크 액세스(이전 명칭: CORS-RFC1918)는 웹사이트가 비공개 네트워크의 서버에 요청을 전송하는 기능을 제한합니다.

Chrome은 이미 사양의 일부를 구현했습니다. Chrome 96부터는 안전한 컨텍스트만 비공개 네트워크 요청을 할 수 있습니다. 자세한 내용은 이전 블로그 게시물을 참고하세요.

또한 이 사양은 웹사이트에서 임의의 요청을 전송하기 전에 비공개 네트워크의 서버에 권한 부여를 명시적으로 요청해야 하도록 교차 출처 리소스 공유 (CORS) 프로토콜을 확장합니다.

PNA에서 IP 주소를 분류하고 비공개 네트워크를 식별하는 방법

IP 주소는 다음과 같은 3가지 IP 주소 공간으로 분류됩니다. - public - private - local

로컬 IP 주소 공간에는 RFC1122의 섹션 3.2.1.3에 정의된 IPv4 루프백 주소 (127.0.0.0/8) 또는 RFC4291의 섹션 2.5.3에 정의된 IPv6 루프백 주소 (::1/128)인 IP 주소가 포함됩니다.

비공개 IP 주소 공간에는 RFC1918에 정의된 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, RFC3927에 정의된 링크-로컬 주소 169.254.0.0/16, RFC4193에 정의된 고유한 로컬 IPv6 유니캐스트 주소fc00::/7, RFC4193에 정의된 고유 로컬 IPv6 유니캐스트 주소fc00::/7, fe80::/10RFC4193}에 정의된 IPv4 주소{/1{/1-RFC4-6}RFC4291

공개 IP 주소 공간에는 이전에 언급되지 않은 다른 모든 주소가 포함됩니다.

로컬 IP 주소는 공개 IP 주소보다 비공개 수준이 더 높은 것으로 간주되는 비공개 IP 주소보다 비공개 수준이 더 높은 것으로 간주됩니다.

가용성이 높은 네트워크가 가용성이 낮은 네트워크에 요청을 전송하면 요청은 비공개입니다.
비공개 네트워크 액세스 (CORS-RFC1918)에서 공개, 비공개, 로컬 네트워크 간의 관계

의견 요청: 사설 네트워크용 CORS (RFC1918)에서 자세히 알아보세요.

프리플라이트 요청

배경

실행 전 요청은 부작용이 있을 수 있는 HTTP 요청을 전송하기 전에 대상 웹사이트에서 권한을 요청하는 데 사용되는 교차 출처 리소스 공유 (CORS) 표준에서 도입한 메커니즘입니다. 이렇게 하면 대상 서버가 CORS 프로토콜을 이해하고 CSRF 공격 위험을 크게 줄일 수 있습니다.

권한 요청은 예정된 HTTP 요청을 설명하는 특정 CORS 요청 헤더와 함께 OPTIONS HTTP 요청으로 전송됩니다. 응답에는 예정된 요청에 명시적으로 동의하는 특정 CORS 응답 헤더가 포함되어야 합니다.

CORS 프리플라이트를 나타내는 시퀀스 다이어그램 OPTIONS HTTP 요청이 대상으로 전송되고 200 OK가 반환됩니다. 그런 다음 CORS 요청 헤더가 전송되어 CORS 응답 헤더가 반환됩니다.

비공개 네트워크 액세스의 새로운 기능

실행 전 요청에 새로운 요청 및 응답 헤더 쌍이 도입되었습니다.

  • 모든 PNA 프리플라이트 요청에 Access-Control-Request-Private-Network: true가 설정됩니다.
  • 모든 PNA 프리플라이트 응답에 Access-Control-Allow-Private-Network: true를 설정해야 합니다.

PNA의 실행 전 요청은 요청 메서드 및 모드에 관계없이 모든 비공개 네트워크 요청에 대해 전송됩니다. cors 모드뿐만 아니라 no-cors 및 기타 모든 모드에서 요청에 앞서 전송됩니다. 요청 모드 및 시작자가 응답 콘텐츠를 사용할 수 있는지 여부와 관계없이 모든 비공개 네트워크 요청이 CSRF 공격에 사용될 수 있기 때문입니다.

대상 IP 주소가 개시자보다 비공개 수준이 더 높은 경우, PNA에 대한 실행 전 요청도 동일 출처 요청에 대해 전송됩니다. 이는 프리플라이트 요청이 교차 출처 요청에만 적용되는 일반 CORS와는 다릅니다. 동일 출처 요청에 대한 실행 전 요청은 DNS 리바인딩 공격으로부터 보호합니다.

관찰 가능한 동작은 요청 모드에 따라 다릅니다.

비 CORS 모드

예를 들어 https://foo.example/index.html<img src="https://bar.example/cat.gif" alt="dancing cat"/>를 삽입하고 bar.exampleRFC 1918에 따라 비공개 IP 주소인 192.168.1.1을 확인합니다.

Chrome은 먼저 프리플라이트 요청을 보냅니다.

HTTP/1.1 OPTIONS /cat.gif
Origin: https://foo.example
Access-Control-Request-Private-Network: true

이 요청이 성공하려면 서버가 다음과 같이 응답해야 합니다.

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Private-Network: true

그러면 Chrome이 실제 요청을 전송합니다.

HTTP/1.1 GET /cat.gif
...

서버가 정상적으로 응답할 수 있는 응답입니다.

CORS 모드

https://foo.example/index.html가 다음 코드를 실행한다고 가정해 보겠습니다.

await fetch('https://bar.example/delete-everything', {
  method: 'PUT',
  credentials: 'include',
})

다시 한번 bar.example192.168.1.1로 확인된다고 가정해 보겠습니다.

Chrome은 먼저 프리플라이트 요청을 보냅니다.

HTTP/1.1 OPTIONS /delete-everything
Origin: https://foo.example
Access-Control-Request-Method: PUT
Access-Control-Request-Credentials: true
Access-Control-Request-Private-Network: true

이 요청이 성공하려면 서버가 다음과 같이 응답해야 합니다.

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Credentials: true
Access-Control-Allow-Private-Network: true

그러면 Chrome이 실제 요청을 전송합니다.

HTTP/1.1 PUT /delete-everything
Origin: https://foo.example

서버가 일반적인 CORS 규칙에 따라 응답할 수 있는 경우는 다음과 같습니다.

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://foo.example

웹사이트가 영향을 받는지 확인하는 방법

Chrome 104부터 비공개 네트워크 요청이 감지되면 프리플라이트 요청이 먼저 전송됩니다. 이 실행 전 요청이 실패하면 최종 요청이 계속 전송되지만 DevTools 문제 패널에 경고가 표시됩니다.

Devtools Issues 패널에서 프리플라이트 요청 실패 경고 여기에는 특정 요청 및 영향을 받는 리소스에 대한 세부정보와 함께 비공개 네트워크 요청이 해당 요청을 허용하는 리소스에만 전송되도록 합니다.

영향을 받은 프리플라이트 요청은 네트워크 패널에서도 확인하고 진단할 수 있습니다.

localhost의 DevTools Network 패널에서 프리플라이트 요청에 실패하면 501 상태가 표시됩니다.

요청이 비공개 네트워크 액세스 규칙 없이 정기적인 CORS 프리플라이트를 트리거한 경우, 두 개의 프리플라이트가 네트워크 패널에 나타날 수 있으며, 첫 번째는 항상 실패한 것으로 나타납니다. 이는 알려진 버그이므로 무시해도 됩니다.

DevTools Network 패널에서 프리플라이트가 성공하기 전에 허위로 실패한 프리플라이트 요청입니다.

프리플라이트 성공이 적용된 경우 발생하는 상황을 검토하려면 Chrome 98부터 다음 명령줄 인수를 전달합니다.

--enable-features=PrivateNetworkAccessRespectPreflightResults

프리플라이트 요청에 실패하면 가져오기에 실패합니다. 이를 통해 출시 계획의 두 번째 단계 후 웹사이트가 작동하는지 테스트할 수 있습니다. 오류는 위에 언급된 DevTools 패널을 사용하여 경고를 진단하는 것과 동일한 방법으로 진단할 수 있습니다.

웹사이트가 영향을 받은 경우 취할 조치

이 변경사항이 Chrome 104에 배포되어도 웹사이트에 영향을 주지 않을 것으로 예상됩니다. 하지만 영향을 받는 요청 경로를 업데이트하여 웹사이트가 예상대로 계속 실행되도록 하는 것이 좋습니다.

다음과 같은 두 가지 솔루션을 사용할 수 있습니다.

  1. 서버 측에서 프리플라이트 요청 처리
  2. 엔터프라이즈 정책으로 PNA 검사 사용 중지

서버 측에서 실행 전 요청 처리

영향을 받는 가져오기의 대상 서버를 업데이트하여 PNA 프리플라이트 요청을 처리합니다. 먼저 영향을 받는 경로에서 표준 CORS 실행 전 요청에 대한 지원을 구현합니다. 그런 다음 새 응답 헤더 2개에 대한 지원을 추가합니다.

서버가 실행 전 요청 (CORS 헤더가 있는 OPTIONS 요청)을 수신하면 서버는 Access-Control-Request-Private-Network: true 헤더가 있는지 확인해야 합니다. 이 헤더가 요청에 있으면 서버는 Origin 헤더와 요청 경로를 기타 관련 정보 (예: Access-Control-Request-Headers)와 함께 검사하여 요청이 허용해도 안전한지 확인해야 합니다. 일반적으로 개발자가 제어하는 단일 출처에 대한 액세스를 허용해야 합니다.

서버가 요청을 허용하기로 결정하면 필요한 CORS 헤더와 새 PNA 헤더로 204 No Content (또는 200 OK)에 응답해야 합니다. 이러한 헤더에는 Access-Control-Allow-Origin, Access-Control-Allow-Private-Network: true, 필요에 따라 다른 헤더도 포함됩니다.

구체적인 시나리오는 를 참고하세요.

엔터프라이즈 정책을 사용하여 비공개 네트워크 액세스 검사 사용 중지

사용자를 관리할 수 있는 권한이 있으면 다음 정책 중 하나를 사용하여 비공개 네트워크 액세스 검사를 사용 중지할 수 있습니다.

자세한 내용은 Chrome 정책 관리 이해하기를 참고하세요.

의견 보내기

공개 네트워크의 요청을 기대하는 비공개 네트워크 내에서 웹사이트를 호스팅하는 경우 Chrome팀은 여러분의 의견과 사용 사례에 관심을 가지고 있습니다. crbug.com에서 Chromium 관련 문제를 신고하여 Google에 알리고 구성요소를 Blink>SecurityFeature>CORS>PrivateNetworkAccess로 설정하세요.

다음 단계

다음으로 Chrome은 웹 작업자(전담 작업자, 공유 작업자, 서비스 작업자)까지 비공개 네트워크 액세스 확인을 확장합니다. 잠정적으로 Chrome 107에서 경고 표시를 시작하는 것을 목표로 합니다.

그런 다음 Chrome은 iframe 및 팝업을 포함한 탐색을 포함하도록 비공개 네트워크 액세스 확인을 확장합니다. 잠정적으로 Chrome 108에서 경고 표시를 시작하는 것을 목표로 합니다.

두 경우 모두 웹 개발자가 호환성 위험을 조정하고 예상할 시간을 주기 위해 비슷한 단계적 출시를 신중하게 진행할 예정입니다.

감사의 말

표지 사진: 마크 올슨, Unsplash