...
Chrome PNA (Private Network Access)
사설망 접근(private network access) 이란, 비인증된 공인(public) 웹사이트에서, 사이트를 방문한 사용자의 와 같은 사설 네트워크망(localhost(127.0.0.1) or 192.168.0.* 아이피) 엔드포인트에 엑세스하려 할때, 브라우저가 요청을 제한하는 새로운 보안 향상 WSC 사양을 말한다.
PNA 동작 메커니즘은 CORS(Cross-Origin Resource Sharing) 정책을 확장한 개념으로 적용된다. 그래서 사이트에서 사설 네트워크 서버의 허가를 우선 예비 요청(Preflight) 하고 브라우저가 요청을 승인한 경우에만, 공공 웹사이트에서 사설 네트워크 서버의 리소스에 엑세스가 가능하고 그렇지 않으면 CORS 에러가 뜨게 된다.
즉, 앞으로 공공 인터넷 웹사이트에서 내부 네트워크 자원에 접근하려면 브라우저의 허락을 받아야만 하는 것이다.
PNA 탄생 배경
브라우저를 통한 네트워크 침입
이 사양은 브라우저를 통해 침투하는 방식의 해킹 공격을 보다 어렵게 만들겠다는 취지로 탄생 되었다. 브라우저는 많은 서비스와 상호 작용해야 하기 때문에, 기본적으로 로컬 네트워크 내부의 거의 모든 리소스에 연결할 수 있다는 특징을 악용하여, 브라우저는 로컬 네트워크에 대한 공격을 위한 교두보로 프록시로서 이용되왔었다.
예를들어 악성 웹사이트를 개설해 두고 피해자를 사이트 접속을 유도함으로써 피해자의 네트워크에 들어가 엔드포인트를 감염시키는 게 가능하다. 사용자가 악성 웹사이트에 액세스하면 브라우저는 사용자 모르게 라우터에 자동 요청을 보내 라우터의 인증을 우회할 수 있기 때문에, 악의적인 웹사이트에서 라우터 설정을 수정할 수 있는 악성 코드를 보내 라우터를 조작하는 식으로 감염시킨다.
실제로 해커가 CSRF 공격을 통해 300,000개 이상의 무선 라우터에 대한 DNS 서버 설정을 변경하여 정보를 탈취한 사례도 있다.
- 사설 내부망을 사용하고 있는 사용자가 악의적인 사이트에 접속한다.
- 악성 자바스크립트가 로컬 네트워크 내부의 컴퓨터에서 로드되어 로컬 컴퓨터가 라우터의 DNS 설정을 자동으로 변경하도록 한다.
- 라우터는 네트워크의 모든 디바이스에 대해 악성 네임서버(DNS)를 사용하도록 설정됨에 따라, 해당 망에 연결된 모든 사용자들의 라우팅 요청을 오염시킨다.
- 금융(또는 기타) 사이트에 연결을 시도하는 디바이스는 이제 로그인 자격 증명을 캡처할 수 있는 가짜 웹사이트로 리다이렉션 될 수 있다.
이러한 보안적인 취약점 때문에 브라우저는 이제 사설망에 대해서 검사를 철저히 한다는 개념으로 PNA 사양이 탄생하게 된 것이다. 그러면 각종 엔드포인트 장비들을 노리는 CSRF(교차 사이트 요청 조작) 공격으로부터 비교적 안전해지게 된다.
Chrome PNA 정책 적용 시기
Google에 따르면 Chrome 94 버전부터 PNA가 등장했으며 현재까지 시범적으로 운용되다가, 2023년 5월에 출시될 Chrome 113 버전에서 정식으로 릴리즈 될 예정이라고 한다. 같은 크로미움 계열인 Edge 브라우저 역시 베타 채널에 도입된 상태이다. 따라서 브라우저 자체에서 비공개 네트워크 요청을 하는 애플리케이션이 있다면 이에 맞게 대처를 해야 할 것이다.
PNA CORS 에러 현상
CORS 의 메세지 종류
일반적인 CORS 메세지
먼저 일반적으로 발생하는 CORS 에러는 다음과 같다. 에러 메세지에서 안내하듯이 이 부분은 백엔드쪽에서 CORS 관련 헤더인 Access-Control-Allow-* 응답만 잘 해주면 별다른 문제없이 해결이 된다.
Access to XMLHttpRequest at 'http://xxxx' from origin 'http://xxxxx' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
PNA CORS 메세지
그런데 서버에서 CORS 관련 헤더 요청 응답을 모두 처리해줬는데, 이번엔 다음과 같은 또다른 CORS 에러가 발생해서 당황한 경험이 있을 것이다.
Access to XMLHttpRequest at 'http://10.x.x.x/xxxx' from origin 'http://xxxx.xxx.com' has been blocked by CORS policy: The request client is not a secure context and the resource is in more-private address space `private`
위 에러 메세지 내용 부분을 해석하자면, 요청 클라이언트가 보안 컨텍스트가 아니며 리소스가 비공개 주소 공간 로컬에 있다는 말이다. 즉, 위에서 다루었던 PNA(Priavte Network Address) 관련 사양이다.
PNA CORS 발생 상황
요청 단계 방향
포스팅 초반에 잠깐 소개했듯이, PNA CORS 발생 상황은 공인 IP에서 사설/로컬 IP로의 낮은 수준으로 가는 요청을 할때 발생된다. 예를 들어 아래 그림에서 Public 네트워크(http://example.com)에서 Private 네트워크(http://router.local) 로의 요청을 하거나, 또는 Private 네트워크에서 Local 호스트의 요청이 이에 해당된다.
- public 네트워크 사이트 → private 네트워크 사이트 (CORS !!)
- public 네트워크 사이트 → 로컬 호스트 (CORS !!)
- private 네트워크 사이트 → 로컬 호스트 (CORS !!)
insecure public website
다만 무조건 공인 웹사이트에서 요청하면 PNA CORS에 걸리는게 아니라, 정확히 말하자면 비인증된* 공인 웹사이트에서 요청하면 걸리는 것이다. 즉, https 나 wss 와 같은 ssl을 먹인 사이트라면 PNA CORS는 발생하지 않게 된다.
도메인 여부
마지막으로 요청을 보낸 공인 웹사이트가 아이피 형태가 아닌 도메인이 씌워져 있을 경우에만 발생한다. 아무리 insecure public website 이라도 도메인 형태가 아닐경우 PNA CORS 에러는 발생하지 않는다.
PNA CORS 관련 헤더
일반적인 CORS 현상을 해결하기 위해 Access-Control-Allow-Origin 헤더를 설정하여 해결 하였 듯이, PNA CORS 역시 관련 헤더인 Access-Control-Allow-Private-Network 헤더를 설정 하면 된다. 이를 도식으로 표현하자면 아래와 같이 된다.
- 하위 자원에 대한 요청을 사설망에 보내기 전에, 앞서 예비 요청(Preflight)을 보낸다.
- 이때 요청 헤더에
Access-Control-Request-Private-Network: true를 실어 서버에 보낸다 - 요청 전달을 받은 서버에서
Access-Control-Allow-Private-Network: true를 통해 허락이나 불허를 응답한다. - 엑세스 허락이 되면 본요청 통신이 이루어지게 된다.
PNA CORS 해결 방법
1. 요청 주체를 변경
앞서 말했듯이 공인 IP라고 해도 insecure일 경우에만 PNA CORS가 발생한다고 하였으니, 호출하는 주체의 scheme를 HTTPS로 설정하면 가져오려는 리소스가 HTTP여도 문제없이 호출이 가능해진다.
혹은 요청하려는 리소스를 사설/로컬 네트워크가 아닌 공인 네트워크로 변경하는 방법도 가능하다.
2. 크롬 브라우저 옵션 변경
크롬 혹은 엣지 브라우저 검색창에 다음 URL로 이동한다.
- chrome://flags
- edge://flags
그리고 Block insecure private network requests 항목과 Send Private Network Access preflights 항목의 설정값을 Disabled로 설정 하면 된다.
3. Chrome Origin Trials 이용
개발자 지원 기능을 이용하여 로컬 네트워크 접근을 허용할 수 있다.
https://developer.chrome.com/origintrials/#/trials/active 로 접속해서, Private Network Access from non-secure contexts 항목의 REGISTER 를 클릭한다. 단, 이 방법은 PNA를 허용할 웹사이트의 API 키를 발급받아 사용하는 형태이기 때문에 사용할 수 있는 기간이 정해져 있다.
4. Access-Control-Allow-Private-Network 헤더 설정
지금까지 소개한 위의 방법은 간단하게 설정만으로 해결이 가능하겠지만, 이는 보안적으로 안전하지 않으며, CORS는 서버가 아닌 브라우저에서 차단하는 메커니즘 이기 때문에, 서비스 이용자들이 직접 자기가 쓰는 컴퓨터의 브라우저 설정을 일일히 조작해야 한다는 번거롭다는 치명적인 단점이 존재한다.
따라서 가장 이상적인 해결책은 백엔드쪽에서 Access-Control-Allow-Private-Network 헤더 설정을 하면 되는 것이다.
HTTP/1.1 OPTIONS localhost:8080/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
# 참고자료
https://www.boannews.com/media/view.asp?idx=104187
https://developer.chrome.com/blog/private-network-access-update/
https://arstechnica.com/information-technology/2022/01/new-chrome-security-measure-aims-to-curtail-an-entire-class-of-web-attack/
이 글이 좋으셨다면 구독 & 좋아요
여러분의 구독과 좋아요는
저자에게 큰 힘이 됩니다.