체인의정석

웹 서비스에서 Content-Security-Policy (CSP), Referer Policy 처리를 통한 보안 강화 본문

개발/frontend

웹 서비스에서 Content-Security-Policy (CSP), Referer Policy 처리를 통한 보안 강화

체인의정석 2026. 1. 5. 16:48
728x90

상황

모회사에서 별도의 WAF와 백신을 설치한 이후에 관련된 ASM(Attack Surface Management) 대시보드를 볼 수 있게 되었다.

ASM은 외부 공격자가 접근할 수 있는 모든 잠재적 지점을 지속적으로 식별하고 분석하며, 보안 취약점을 최소화하는 프로세스라고 한다.

보니 referer policy와 Content-Security-Policy가 적용되지 않아서 보안성 경고가 뜬 부분을 볼 수 있었다.

https://velog.io/@sejinkim/Referrer-Policy%EC%9D%98-%EC%9D%B4%ED%95%B4

 

Referrer-Policy의 이해

사용자 행동 로그 데이터 수집 중 Referer가 유실되었던 사례를 계기로, Referrer-Policy에 관해 자세히 알아보았습니다.

velog.io

Referer Policy - 서버 처리

  • 목적: 브라우저가 HTTP 요청 시 Referer (오타가 있는 원조 헤더 이름) 헤더에 포함할 이전 페이지의 URL 정보(리퍼러 정보)의 양을 제어합니다.
  • 작동 방식: 사용자가 한 웹사이트에서 다른 웹사이트로 이동하거나 리소스를 요청할 때, 목적지 서버에 어떤 출처 정보를 보낼지 결정합니다.
  • 주요 목표: URL에 포함될 수 있는 민감한 정보(예: 세션 토큰, 개인 식별자)의 불필요한 노출을 방지하여 사용자 프라이버시를 보호하는 데 중점을 둡니다.
  • 예시: Referrer-Policy: no-referrer는 어떠한 리퍼러 정보도 보내지 않도록 지시하며, Referrer-Policy: strict-origin-when-cross-origin은 동일 출처 요청 시에는 전체 URL을 보내지만 교차 출처 요청 시에는 출처(origin) 정보만 보내도록 합니다. 

웹 사이트 보안의 기본적인 대전제는 Same Origin Policy(SOP) 동일 출처 정책이다.

가능한 공격 벡터를 줄이기 위해, 다른 출저와의 상호작용을 제한하는 보안 정책이다.

동일한 출저가 아닌 경우 Cross-site 또는 Cross-Origin 이라고 하며, 개인정보 보호 및 웹 공격 방어 차원에서 특정 기능이나 정보가 제한됩니다.

먼저 referer policy에 대해서 찾아본 결과  Referer의 정의는 현재 요청을 보낸 페이지의 절대 혹은 부분 주소라고 한다. 리소스 요청이나 사용자의 링크 클릭에 존재할 수 있으며, 여기서 정보를 제한하지 않으면 사용자의 개인정보가 노출될 수 있기 때문에 제한을 하는 정책이라고 한다. 일단 SOP의 경우에는 문제를 삼지 않지만 cross-origin 요청일 때는 엄격하게 제한하는 것이 기본적인 기조라고 한다.

따아서 cross-origin요청일 때는 "strict-origin-when-cross-origin" 요청을 주면 된다.

반영하는 방법은 다음과 같다.

https://kku-jun.tistory.com/48

 

Referer Policy 적용하기

혹시 프로젝트를 진행하면서 이미지 url을 통해 접근은 가능하나 개발중인 서비스앱 내부에서는 호출하지 못한 경험이 있는가? 필자는 다음 경험을 Referer policy를 정의하면서 접근할 수 있게 되

kku-jun.tistory.com

 

해당 방법은 간단한데 웹서버에서

		// 보안 헤더 설정
		w.Header().Set("Referrer-Policy", "strict-origin-when-cross-origin")

위 언어는 go언어지만 해당 방식으로 보안 헤더를 서버에서 설정해 주면 

위와 같이 referrer policy가 반영되게 된다.

CSP - 서버 처리

다음으로 작업한 부분은 CSP 반영이다.

Content-Security-Policy (CSP)
  • 목적: 웹사이트 관리자가 페이지에서 로드할 수 있는 리소스(스크립트, 이미지, 스타일 등)의 출처를 제어할 수 있도록 합니다.
  • 작동 방식: 신뢰할 수 있는 콘텐츠 소스(도메인)를 지정하여, 브라우저가 승인되지 않은 출처의 악성 콘텐츠를 로드하거나 실행하는 것을 방지합니다.
  • 주요 목표: 교차 사이트 스크립팅(XSS) 및 데이터 삽입 공격과 같은 특정 유형의 공격을 탐지하고 완화하는 데 효과적인 추가 보안 계층입니다.
  • 예시: Content-Security-Policy: script-src 'self' https://trusted-scripts.com;은 브라우저에게 자체 출처와 trusted-scripts.com에서만 스크립트를 로드하도록 지시합니다. 

여기서 말하는 CSP는 콘텐츠 보안 정책으로 교차 사이트 스크립팅과 데이터 주입 공격 등을 방어하기 위한 추가 보안 계층이라고 한다.

There is missing header: Content-Security-Policy. The HTTP Content-Security-Policy response header allows web site administrators to control resources the user agent is allowed to load for a given page.

만약 http 요청에서 아래와 같이 이미 정책이 있다면 괜찮지만 해당 정책이 없다면 외부로부터의 호출에 있어서 보안 계층이 없어지는 것이기 때문에 활성화를 시켜주어야한다.

CSP를 활성화하려면 Content-Security-Policy HTTP 헤더를 반환하도록 웹 서버를 구성해야 한다.

w.Header().Set("Content-Security-Policy", 
    "default-src 'self'; 
     script-src 'self' 'unsafe-inline' 'unsafe-eval'; 
     style-src 'self' 'unsafe-inline'; 
     img-src 'self' data: https:; 
     font-src 'self' data:; 
     connect-src 'self'")

https://developer.mozilla.org/ko/docs/Web/HTTP/Guides/CSP

 

컨텐츠 보안 정책 (CSP) - HTTP | MDN

CSP의 주요 목표는 XSS 공격을 완화하고 보고하는 것입니다. XSS 공격은 서버에서 받은 콘텐츠를 브라우저가 신뢰한다는 점을 악용합니다. 브라우저는 콘텐츠의 출처를 신뢰하기 때문에 콘텐츠가

developer.mozilla.org

 

Referer Policy & CSP 프론트엔드 처리

또한 두 부분 모두 프론트엔드에서 정적 파일 실행하는 부분도 ASM 모니터링 툴에 걸려서 업데이트를 진행해야 했었다.

만약 메타 마스크도 들어간다면 프론트엔드에서는 아래와 같이 정책을 짜면 된다.

파일명 : next.config.mjs

/** @type {import('next').NextConfig} */
const nextConfig = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          {
            key: 'Referrer-Policy',
            value: 'strict-origin-when-cross-origin',
          },
          {
            key: 'Content-Security-Policy',
            value: [
              "default-src 'self'",
              "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.yourdomain.com",
              "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdn.jsdelivr.net",
              "img-src 'self' data: https:",
              "font-src 'self' data: https://fonts.gstatic.com https://cdn.jsdelivr.net",
              "connect-src 'self' https://*.yourdomain.com https://*.metamask.io https://*.metamask-api.io https://*.arbitrum.io https://*.infura.io https://cdn.jsdelivr.net wss://*.metamask.io wss://*.metamask-api.io",
            ].join('; '),
          },
        ],
      },
    ];
  },
};

export default nextConfig;

이렇게 사용되는 외부 도메인 호출을 모두 CSP 정책에 넣어주어야 외부 공격으로부터 더 안전한 서비스를 만들 수 있게 된다.

또한 프론트에서 상세하게 CSP정책이 있기 때문에 이렇게 도메인을 하나하나 넣어주는 작업은 백엔드에서는 할 필요가 없다.

728x90
반응형
Comments