날먹을 위한 몸부림/쉽지않음

평소에 보기 쉽지 않음 - Access-Control-Allow-Private-Network

프로그래밍하는 지팡이 2024. 12. 5. 18:05

Access-Control-Allow-Private-Network

 

Access-Control-Allow-Private-Network 헤더는 웹 애플리케이션이 로컬 네트워크 리소스에 접근할 수 있도록 허용하기 위해 사용됨. 이는 특히 CORS(Cross-Origin Resource Sharing) 정책의 일부로, 로컬 네트워크 보호와 관련된 보안 강화를 위해 도입된 새로운 기능임

 

사용 배경

웹 애플리케이션은 보안상의 이유로 기본적으로 다른 출처(origin)에 있는 리소스에 접근할 수 없음. 로컬 네트워크의 민감한 데이터에 접근하는 것은 특히 더 제한되어야 함. 이 헤더는 웹 브라우저가 **프라이빗 네트워크(예: 로컬 서버, IoT 디바이스)**에 접근하는 요청을 처리할 수 있도록 허가하는 역할을 함

 

다음은 사고가 발생하는 대략적인 순서임

 

  • 웹 애플리케이션 취약점 발견: 악성 웹사이트가 CORS 설정이 잘못된 로컬 네트워크 장치(예: 라우터, IoT 디바이스)에 접근.
  • 민감한 데이터 탈취: 해당 디바이스로부터 비밀번호, 설정 정보 등 민감한 데이터를 무단으로 요청 및 수집.
  • 리소스 악용: 네트워크 장치를 악의적으로 재설정하거나, 원격 코드 실행 등의 공격 발생.
  • 피해: 내부 네트워크까지 침투해 데이터 유출 및 시스템 마비.

 

주변에서 볼 수 있는곳

그리드 프로그램(아프리카tv, 치지직 등)

하드웨어를 사용하는 프로그램(아두이노 웹 블록코딩)

 

작동 방식

최신 브라우저(Chrome, edge 등)은 하위 리소스의 비공개 네트워크 요청보다 먼저 CORS 프리플라이트 요청을 전송하여 대상 서버의 명시적 권한을 요청하기 시작합니다. 이 사전 비행 요청은 새 헤더 Access-Control-Request-Private-Network: true를 전송하며 이에 대한 응답은 상응하는 헤더 Access-Control-Allow-Private-Network: true를 전송해야 합니다. 목표는 비공개 네트워크의 라우터 및 기타 기기를 대상으로 하는 교차 사이트 요청 위조 (CSRF) 공격으로부터 사용자를 보호하는 것입니다. 이러한 공격으로 수십만 명의 사용자가 영향을 받았으며 공격자가 사용자를 악성 서버로 리디렉션할 수 있었습니다.

출처 : https://developer.chrome.com/blog/private-network-access-preflight?hl=ko#introduction

 

이걸 왜 만든거임

로컬 네트워크 엑세스를 완전히 없애지 않고 남겨둔건 몇가지 이유가 있음

  • 로컬네트워크의 유용성
    많은 웹 애플리케이션이 로컬 네트워크의 리소스와 통신해야하는 합법적인 요구가 있을 수 있음
    예: 프린터, iot디바이스, 라우터 등
  • 사용자 경험보장
    웹에서 로컬 네트워크의 디바이스를 설정하는 경우가 있는데 그런 작업들이 불가능해질 수 있음
    예: 프린터 설정 페이지가 동작하지 않음
  • 보안과 접근의 균형
    무조건 차단하면 보안은 강화되지만 실질적인 서비스는 불가능해지는 경우가 있음. 이 헤더는 안전한 요청만 허용할 수 있는 제어권을 서버와 브라우저에게 제공함
  • 최소한의 신뢰 기반 통신
    이 헤더는 비공개 네트워크 접근은 명시적 허가가 필요하다는 원칙을 적용함. 서버가 Access-Control-Allow-Private-Network: true 를 전송하지 않으면 접근이 차단됨

 

이거 왜 씀

웹에서 모바일 기기의 블루투스 비콘 스캔 기능을 사용해야했음

연결 기반 블루투스 기기들이 아닌 주로 위치기반으로 사용되는 비콘을 스캔해야 했음

웹 블루투스는 실험적 기능이라서 직접 활성화 시켜야하며 연결 기반만 작동하고 비콘 스캔은 지원하지 않음

 

가장 자주 사용되는 해결방법은 웹뷰를 포함하는 앱을 만들고 해당 앱에서 비콘을 스캔한 뒤 웹뷰로 넘겨주고 웹에서 받은 그 비콘 정보를 사용하는 방법임

그 방법은 그냥 재미 없을거 같아서 로컬 서버로 작동하는 비콘 스캔용 앱을 만듬

위 앱은 실행하면 간단한 상태를 출력하고 포그라운드에서 비콘을 스캔하며 로컬 api요청을 처리함

 

요약: 그냥 재밌을거 같아서

 

 

fastapi에서 설정 방법

fastapi에서 CORS미들웨어를 추가할 수 있음

Access-Control-Allow-Private-Network는 CORS프리플라이트 요청을 전송해서 명시적으로 권한을 요청함

위 두가지를 알고 있다면 다음과 같이 코드를 작성할 수 있음

베이스는 starlette의 CORS 미들웨어의 생성자를 사용했고 그냥 추가로 인자 하나 더 들어간거 말고는 차이가 없음

타입힌트를 신경쓰지 않는다면 더 간단하게도 작성가능

 

from typing import Optional, Sequence
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware as _CORSMiddleware
from starlette.types import ASGIApp
class CORSMiddleware(_CORSMiddleware):
def __init__(
self,
app: ASGIApp,
allow_origins: Sequence[str] = (),
allow_methods: Sequence[str] = ("GET",),
allow_headers: Sequence[str] = (),
allow_credentials: bool = False,
allow_private_network: bool = False,
allow_origin_regex: Optional[str] = None,
expose_headers: Sequence[str] = (),
max_age: int = 600,
) -> None:
super().__init__(
app,
allow_origins,
allow_methods,
allow_headers,
allow_credentials,
allow_origin_regex,
expose_headers,
max_age,
)
if allow_private_network:
self.preflight_headers[
"Access-Control-Allow-Private-Network"
] = "true"
view raw middleware.py hosted with ❤ by GitHub

 

 

추가 정보가 필요하다면 starlette의 구현을 CORS 미들웨어를 살펴보면됨

 

fastapi의 CORS 미들웨어. starlette의 CORS 미들웨어를 그대로 내보내고있음
CORS의 프리플라이트를 처리하는 부분

 

진짜 특별한 구현이 필요하다면 ASGI를 준수하는 미들웨어를 직접 구현해도 가능

 

다운로드

Access-Control-Allow-Private-Network 를 처리하는 비콘 스캔 로컬 서버 앱 다운로드 링크(안드로이드)

https://boa9448.tistory.com/45