최신 웹 애플리케이션에서 사용자 데이터를 안전하게 호스팅

David Dworken
David Dworken

많은 웹 애플리케이션은 사용자가 제어하는 콘텐츠를 표시해야 합니다. 이는 사용자가 업로드한 이미지 (예: 프로필 사진)를 제공하는 것처럼 간단하거나 사용자가 제어하는 HTML을 렌더링하는 것처럼 복잡할 수 있습니다 (예: 웹 개발 튜토리얼). 이를 안전하게 수행하는 것은 항상 어려웠기 때문에 Google에서는 대부분의 웹 애플리케이션 유형에 적용할 수 있는 쉽지만 안전한 솔루션을 찾기 위해 노력해 왔습니다.

사용자 관리 콘텐츠를 안전하게 게재하기 위한 기존 솔루션은 샌드박스 도메인을 사용하는 것입니다. 기본 아이디어는 애플리케이션의 기본 도메인이 example.com인 경우 exampleusercontent.com에서 모든 신뢰할 수 없는 콘텐츠를 게재할 수 있다는 것입니다. 이 두 도메인은 교차 사이트이므로 exampleusercontent.com의 악성 콘텐츠는 example.com에 영향을 미칠 수 없습니다.
이 접근 방식은 이미지, 다운로드, HTML을 비롯한 모든 종류의 신뢰할 수 없는 콘텐츠를 안전하게 제공하는 데 사용할 수 있습니다. 이미지나 다운로드에 이를 사용할 필요는 없어 보이지만, 특히 기존 브라우저에서 콘텐츠 스니핑의 위험을 방지하는 데 도움이 됩니다.
샌드박스 도메인은 업계 전반에서 널리 사용되고 있으며 오랫동안 잘 작동했습니다. 하지만 두 가지 주요 단점이 있습니다.

  • 애플리케이션은 콘텐츠 액세스를 단일 사용자로 제한해야 하는 경우가 많으며, 이를 위해서는 인증 및 승인을 구현해야 합니다. 샌드박스 도메인은 의도적으로 기본 애플리케이션 도메인과 쿠키를 공유하지 않으므로 이를 안전하게 실행하는 것은 매우 어렵습니다. 인증을 지원하려면 사이트에서 기능 URL을 사용하거나 샌드박스 도메인에 별도의 인증 쿠키를 설정해야 합니다. 이 두 번째 방법은 많은 브라우저가 교차 사이트 쿠키를 기본적으로 제한하는 최신 웹에서 특히 문제가 됩니다.
  • 사용자 콘텐츠는 기본 사이트와 격리되지만 다른 사용자 콘텐츠와는 격리되지 않습니다. 이렇게 하면 악성 사용자 콘텐츠가 샌드박스 도메인의 다른 데이터를 공격할 위험이 있습니다 (예: 동일 출처 데이터 읽기).

또한 샌드박스 도메인은 리소스가 격리된 도메인으로 명확하게 분할되므로 피싱 위험을 완화하는 데 도움이 됩니다.

사용자 콘텐츠를 게재하기 위한 최신 솔루션

시간이 지남에 따라 웹이 발전했으며 이제 신뢰할 수 없는 콘텐츠를 더 쉽고 안전하게 게재할 수 있습니다. 여기에는 여러 가지 접근 방식이 있으므로 현재 Google에서 널리 사용 중인 두 가지 솔루션을 간략히 설명하겠습니다.

접근 방식 1: 비활성 사용자 콘텐츠 게재

사이트에서 비활성 사용자 콘텐츠 (예: 이미지 및 다운로드 등 HTML 또는 JavaScript가 아닌 콘텐츠)만 제공하면 되는 경우 이제 격리된 샌드박스 도메인 없이도 안전하게 처리할 수 있습니다. 두 가지 주요 단계가 있습니다.

  • 항상 Content-Type 헤더를 모든 브라우저에서 지원되고 활성 콘텐츠가 포함되지 않도록 보장되는 잘 알려진 MIME 유형으로 설정합니다. 확실하지 않은 경우 application/octet-stream을 선택하는 것이 안전합니다.
  • 또한 브라우저가 응답을 완전히 격리할 수 있도록 항상 아래 응답 헤더를 설정하세요.
응답 헤더 목적

X-Content-Type-Options: nosniff

콘텐츠 스니핑 방지

Content-Disposition: attachment; filename="download"

렌더링 대신 다운로드를 트리거합니다.

Content-Security-Policy: sandbox

콘텐츠가 별도의 도메인에서 제공되는 것처럼 샌드박스 처리합니다.

Content-Security-Policy: default-src ‘none'

JavaScript 실행 (및 하위 리소스 포함)을 사용 중지합니다.

Cross-Origin-Resource-Policy: same-site

페이지가 교차 사이트에 포함되지 않도록 차단

이러한 헤더 조합을 사용하면 응답을 애플리케이션에서 하위 리소스로만 로드하거나 사용자가 파일로만 다운로드할 수 있습니다. 또한 헤더는 CSP 샌드박스 헤더와 default-src 제한을 통해 브라우저 버그에 대한 여러 계층의 보호 기능을 제공합니다. 전반적으로 위에 설명된 설정은 이러한 방식으로 제공된 응답이 삽입 또는 격리 취약점으로 이어질 수 없다는 높은 수준의 확신을 제공합니다.

심층 방어

위의 솔루션은 일반적으로 XSS에 대한 충분한 방어 수단이지만, 보안 레이어를 추가로 제공하기 위해 적용할 수 있는 추가적인 강화 조치가 많이 있습니다.

  • IE11과의 호환성을 위해 X-Content-Security-Policy: sandbox 헤더를 설정합니다.
  • Content-Security-Policy: frame-ancestors 'none' 헤더를 설정하여 엔드포인트가 삽입되지 않도록 차단합니다.
  • 다음과 같이 격리된 하위 도메인에서 사용자 콘텐츠를 샌드박스 처리합니다.
    • 격리된 하위 도메인에서 사용자 콘텐츠를 게재합니다 (예: Google은 product.usercontent.google.com과 같은 도메인을 사용함).
    • Cross-Origin-Opener-Policy: same-originCross-Origin-Embedder-Policy: require-corp를 설정하여 교차 출처 격리를 사용 설정합니다.

접근 방식 2: 활성 사용자 콘텐츠 게재

기존 샌드박스 도메인 접근 방식의 약점 없이도 활성 콘텐츠 (예: HTML 또는 SVG 이미지)를 안전하게 게재할 수 있습니다.
가장 간단한 방법은 Content-Security-Policy: sandbox 헤더를 활용하여 브라우저에 응답을 격리하도록 지시하는 것입니다. 현재 일부 웹브라우저에서만 샌드박스 문서에 프로세스 격리를 구현하고 있지만 브라우저 프로세스 모델이 지속적으로 개선되면 샌드박스 콘텐츠와 삽입 애플리케이션의 분리가 개선될 수 있습니다. SpectreJS렌더러 손상 공격이 위협 모델에 해당하지 않는 경우 CSP 샌드박스를 사용하는 것이 충분한 해결책일 수 있습니다.
Google에서는 샌드박스 도메인 개념을 현대화하여 신뢰할 수 없는 활성 콘텐츠를 완전히 격리할 수 있는 솔루션을 개발했습니다. 핵심 아이디어는 다음과 같습니다.

  • 공개 서픽스 목록에 추가되는 새 샌드박스 도메인을 만듭니다. 예를 들어 PSL에 exampleusercontent.com를 추가하면 foo.exampleusercontent.combar.exampleusercontent.com가 교차 사이트이므로 서로 완전히 격리됩니다.
  • *.exampleusercontent.com/shim와 일치하는 URL은 모두 정적 shim 파일로 라우팅됩니다. 이 shim 파일에는 message 이벤트 핸들러를 수신 대기하고 수신한 콘텐츠를 렌더링하는 짧은 HTML 및 JavaScript 스니펫이 포함되어 있습니다.
  • 이를 사용하기 위해 제품은 $RANDOM_VALUE.exampleusercontent.com/shim에 iframe 또는 팝업을 만들고 postMessage를 사용하여 렌더링을 위해 신뢰할 수 없는 콘텐츠를 쉬밍으로 전송합니다.
  • 렌더링된 콘텐츠는 Blob으로 변환되고 샌드박스 처리된 iframe 내에서 렌더링됩니다.

기존 샌드박스 도메인 접근 방식과 비교하면 모든 콘텐츠가 고유한 사이트에서 완전히 격리됩니다. 또한 기본 애플리케이션에서 렌더링할 데이터 검색을 처리하도록 하면 더 이상 기능 URL을 사용할 필요가 없습니다.

결론

이 두 가지 솔루션을 함께 사용하면 googleusercontent.com와 같은 기존 샌드박스 도메인에서 서드 파티 쿠키 차단과 호환되는 더 안전한 솔루션으로 이전할 수 있습니다. Google에서는 이미 이러한 솔루션을 사용하도록 많은 제품을 이전했으며 내년에도 더 많은 이전을 계획하고 있습니다.