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

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은 비공개 네트워크 하위 리소스 요청보다 먼저 프리플라이트 요청을 전송하여 실험합니다.
    • 프리플라이트 실패 시에는 개발자 도구에서 경고만 표시되며, 비공개 네트워크 요청에는 영향을 미치지 않습니다.
    • Chrome은 호환성 데이터를 수집하고 가장 큰 영향을 받은 웹사이트에 연락합니다.
    • 이 기능은 기존 웹사이트와 광범위하게 호환됩니다.
  2. 빠르면 Chrome 113부터 다음과 같은 변경사항이 적용됩니다.

    • 호환성 데이터에서 변경사항이 충분히 안전하다고 나타나고 필요한 경우 직접 연락을 취한 경우에 시작됩니다.
    • Chrome은 프리플라이트 요청이 성공해야 하며 그렇지 않으면 요청이 실패하도록 적용합니다.
    • 지원 중단 트라이얼은 이 단계의 영향을 받는 웹사이트에서 시간 연장을 요청할 수 있도록 동시에 시작됩니다. 체험 기간은 6개월 이상 지속됩니다.

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

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

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

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

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

IP 주소는 세 가지 IP 주소 공간으로 분류됩니다. - public - private - local

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

비공개 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 unicast 주소 fc00::/7, RFC4291의 섹션 2.5.6에 정의된 링크 로컬 IPv6 unicast 주소 fe80::/10, 매핑된 IPv4 주소 자체가 비공개인 IPv4-mapped IPv6 주소를 포함하여 현재 네트워크 내에서만 의미가 있는 IP 주소가 포함됩니다.

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

로컬 IP 주소는 비공개 IP 주소보다 비공개 수준이 높으며 비공개 IP 주소는 공개 IP 주소보다 비공개 수준이 높습니다.

사용 가능한 네트워크가 사용 가능한 네트워크에 요청을 전송하는 경우 요청은 비공개입니다.
비공개 네트워크 액세스 (CORS-RFC1918)의 공개, 비공개, 로컬 네트워크 간의 관계

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

프리플라이트 요청

배경

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

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

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

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

프리플라이트 요청에 새로운 요청 및 응답 헤더 쌍이 도입되었습니다.

  • Access-Control-Request-Private-Network: true는 모든 PNA 프리플라이트 요청에 설정됩니다.
  • Access-Control-Allow-Private-Network: true는 모든 PNA 사전 비행 확인 응답에 설정되어야 합니다.

PNA의 프리플라이트 요청은 요청 방법과 모드와 관계없이 모든 비공개 네트워크 요청에 대해 전송됩니다. cors 모드, no-cors 모드, 기타 모든 모드에서 요청 전에 전송됩니다. 이는 모든 비공개 네트워크 요청이 요청 모드와 응답 콘텐츠가 시작자에 제공되는지 여부와 관계없이 CSRF 공격에 사용될 수 있기 때문입니다.

대상 IP 주소가 시작자보다 더 비공개인 경우 동일 출처 요청에도 PNA의 사전 비행 요청이 전송됩니다. 이는 프리플라이트 요청이 교차 출처 요청 전용인 일반 CORS와는 다릅니다. 동일 출처 요청의 사전 비행 요청은 DNS 재바인딩 공격을 방지합니다.

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

No-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 문제 패널에 실패한 사전 비행 요청 경고가 표시됩니다. 이는 특정 요청과 영향을 받는 리소스에 대한 세부정보와 함께 비공개 네트워크 요청을 허용하는 리소스에만 실행되도록 합니다.

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

localhost의 DevTools Network 패널에서 사전 비행 요청이 실패하면 501 상태가 표시됩니다.

요청이 비공개 네트워크 액세스 규칙 없이 일반 CORS 프리플라이트를 트리거했다면 네트워크 패널에 두 개의 프리플라이트가 표시될 수 있으며, 첫 번째 프리플라이트는 항상 실패한 것으로 표시됩니다. 이는 알려진 버그이므로 무시해도 됩니다.

DevTools Network 패널에서 프리플라이트에 앞서 실패한 프리플라이트 요청이 있습니다.

실행 전 성공이 적용된 경우 어떤 일이 발생하는지 검토하려면 Chrome 98부터 다음 명령줄 인수를 전달하면 됩니다.

--enable-features=PrivateNetworkAccessRespectPreflightResults

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

웹사이트가 영향을 받는 경우 취해야 할 조치

이 변경사항이 Chrome 104에서 출시되더라도 웹사이트가 중단되지는 않을 것으로 예상됩니다. 하지만 웹사이트가 예상대로 계속 실행되도록 영향을 받는 요청 경로를 업데이트하는 것이 좋습니다.

다음 두 가지 해결 방법이 있습니다.

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

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

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

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

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

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

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

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

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

의견 보내기

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

다음 단계

다음으로 Chrome은 비공개 네트워크 액세스 검사를 전용 작업자, 공유 작업자, 서비스 워커와 같은 웹 워커로 확장할 예정입니다. Google은 잠정적으로 Chrome 107에서 경고를 표시하는 것을 목표로 하고 있습니다.

그러면 Chrome에서 iframe 및 팝업을 비롯한 탐색을 포함하도록 비공개 네트워크 액세스 검사를 확장합니다. Chrome 108부터 경고를 표시할 예정입니다.

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

감사의 말씀

표지 사진: Unsplash마크 올슨