CSP가 XSS 공격에 효과적인지 확인

콘텐츠 보안 정책 (CSP)을 사용하면 페이지에 로드된 모든 콘텐츠가 사이트 소유자가 신뢰할 수 있는지 확인할 수 있습니다. CSP는 공격자가 삽입한 안전하지 않은 스크립트를 차단할 수 있기 때문에 교차 사이트 스크립팅 (XSS) 공격을 완화합니다. 그러나 CSP는 충분히 엄격하지 않다면 쉽게 우회될 수 있습니다. 자세한 내용은 엄격한 콘텐츠 보안 정책 (CSP)으로 교차 사이트 스크립팅 (XSS) 완화하기를 참고하세요. Lighthouse는 기본 문서에 적용된 CSP를 수집하고 우회할 수 있는 경우 CSP Evaluator에서 문제를 보고합니다.

시행 모드에서 CSP를 찾을 수 없다는 Lighthouse 보고서 경고입니다.
시행 모드에서 CSP를 찾을 수 없다는 Lighthouse 보고서 경고

우회 불가능한 CSP의 필수 권장사항

CSP를 우회하지 않도록 다음 권장사항을 구현하세요. CSP를 우회할 수 있는 경우 Lighthouse에서 높은 심각도 경고를 표시합니다.

CSP 대상 XSS

XSS를 타겟팅하려면 CSP에 script-src, object-src, base-uri 지시어가 포함되어야 합니다. CSP에 구문 오류도 없어야 합니다.

script-srcobject-src는 각각 안전하지 않은 스크립트와 안전하지 않은 플러그인으로부터 페이지를 보호합니다. 또는 default-src를 사용하여 script-srcobject-src를 비롯한 여러 지시어 대신 광범위한 정책을 구성할 수 있습니다.

base-uri는 스크립트와 같은 모든 상대 URL을 공격자가 제어하는 도메인으로 리디렉션하는 데 사용될 수 있는 승인되지 않은 <base> 태그의 삽입을 방지합니다.

CSP는 nonce 또는 해시를 사용하여 허용 목록 우회를 방지합니다.

script-src의 허용 목록을 구성하는 CSP는 신뢰할 수 있는 도메인에서 들어오는 모든 응답이 안전하며 스크립트로 실행될 수 있다는 가정을 기반으로 합니다. 그러나 이러한 가정은 최신 애플리케이션에는 적용되지 않습니다. JSONP 인터페이스 노출 및 AngularJS 라이브러리의 사본 호스팅과 같은 몇 가지 일반적이고 무해한 패턴을 통해 공격자가 CSP의 한계를 벗어날 수 있습니다.

실제로 애플리케이션 작성자에게는 명확하지 않을 수 있지만 대다수의 script-src 허용 목록은 XSS 버그를 앓고 있는 공격자에 의해 우회될 수 있으며 스크립트 삽입에 대한 보호 기능이 거의 없습니다. 반면 nonce 기반 및 해시 기반 접근 방식은 이러한 문제가 발생하지 않으며 더 안전한 정책을 더 쉽게 채택하고 유지할 수 있도록 합니다.

예를 들어 다음 코드는 신뢰할 수 있는 도메인에 호스팅된 JSONP 엔드포인트를 사용하여 공격자가 제어하는 스크립트를 삽입합니다.

CSP:

script-src https://trusted.example.com

HTML:

<script src="https://trusted.example.com/path/jsonp?callback=alert(document.domain)//"></script>

우회를 방지하려면 CSP에서 nonce나 해시를 사용하는 스크립트를 개별적으로 허용하고 허용 목록 대신 'strict-dynamic'을 사용해야 합니다.

보안 CSP를 위한 추가 권장사항

보안 및 호환성 강화를 위해 다음 권장사항을 구현합니다. CSP가 권장사항을 따르지 않으면 Lighthouse에서 보통 심각도 경고를 표시합니다.

CSP 보고 구성

보고 대상을 구성하면 손상이 있는지 모니터링하는 데 도움이 됩니다. report-uri 또는 report-to 지시어를 사용하여 보고 대상을 설정할 수 있습니다. report-to는 현재 일부 최신 브라우저에서 지원되지 않으므로 둘 다 사용하거나 report-uri만 사용하는 것이 좋습니다.

CSP를 위반하는 콘텐츠가 있으면 브라우저에서 구성된 도착 페이지로 보고서를 전송합니다. 이 대상에서 이러한 보고서를 처리하는 애플리케이션이 구성되어 있는지 확인하세요.

HTTP 헤더에 CSP 정의

CSP는 다음과 같이 메타 태그에서 정의할 수 있습니다.

<meta http-equiv="Content-Security-Policy" content="script-src 'none'">

하지만 가능하면 HTTP 응답 헤더에 CSP를 정의해야 합니다. 메타 태그 앞에 삽입하면 CSP를 우회합니다. 또한 frame-ancestors, sandbox 및 보고는 메타 태그 CSP에서 지원되지 않습니다.

CSP가 이전 버전과 호환되는지 확인

모든 브라우저가 CSP nonce/hash를 지원하는 것은 아니므로 규정을 준수하지 않는 브라우저에서 unsafe-inline를 대체 방안으로 추가하는 것이 좋습니다. 브라우저가 nonce/해시를 지원하는 경우 unsafe-inline는 무시됩니다.

마찬가지로 strict-dynamic는 모든 브라우저에서 지원되지 않습니다. 정책을 준수하지 않는 브라우저에 대해서는 허용 목록을 대체 수단으로 설정하는 것이 좋습니다. strict-dynamic를 지원하는 브라우저에서는 허용 목록이 무시됩니다.

엄격한 CSP 개발 방법

다음은 nonce 기반 정책에 엄격한 CSP를 사용하는 예입니다.

CSP:

script-src 'nonce-random123' 'strict-dynamic' 'unsafe-inline' https:;
object-src 'none';
base-uri 'none';
report-uri https://reporting.example.com;

HTML:

<script nonce="random123" src="https://trusted.example.com/trusted_script.js"></script>

random123는 페이지가 로드될 때마다 서버 측에서 생성된 base64 문자열이 됩니다. 최신 브라우저에서는 nonce와 strict-dynamic로 인해 unsafe-inlinehttps:가 무시됩니다. 엄격한 CSP 채택에 관한 자세한 내용은 엄격한 CSP 가이드를 참고하세요.

Lighthouse 및 CSP Evaluator를 사용하여 CSP에서 우회 가능성을 확인할 수 있습니다. 기존 페이지가 손상될 위험 없이 새 CSP를 테스트하려면 헤더 이름으로 Content-Security-Policy-Report-Only를 사용하여 보고서 전용 모드에서 CSP를 정의하세요. 이렇게 하면 report-toreport-uri로 구성한 모든 보고 대상으로 CSP 위반이 전송되지만 CSP가 실제로 적용되지는 않습니다.