본문 바로가기

FrontEnd

Content security policy[콘텐츠 보안 정책]에 대해 알아보기

반응형

keyword : 보안, 콘텐츠 보안 정책, Content Security Policy, CSP

 

최근 크롬 확장 프로그램의 구조를 분석할 일이 있었습니다.

그러다 리퀘스트 / 리스폰스 요청 후킹 및 콘텐츠 스크립트 인젝션과 관련된 

콘텐츠 보안 정책에 대해 깊게 공부할 필요성을 느끼게 되어 정리합니다.

크롬 확장 프로그램과 워커는 일련의 서버 역할을 하므로, 효과적인 활용을 위해선 서버 측 지식의 공부도 필요합니다.

 

아래 글의 번역입니다.

https://web.dev/csp/
 

 

Content security policy

Content Security Policy can significantly reduce the risk and impact of cross-site scripting attacks in modern browsers.

web.dev

콘텐츠 보안 정책은 최신 브라우저에서 교차 사이트 스크립팅(XSS) 공격의 위험과 영향을 크게 줄일 수 있습니다.
 
웹의 보안 모델은 동일 출처 정책(same-origin policy)에 뿌리를 두고 있습니다.
https://mybank.com의 코드는 https://mybank.com의 데이터에만 액세스할 수 있어야 하며
https://evil.example.com에는 절대 액세스가 허용되지 않아야 합니다.
각 오리진은 개발자의 영역이 아닌 웹의 다른 부분과 격리되어, 개발자에게 안전한 샌드박스를 제공합니다.
이론적으론 완벽히 훌륭합니다만, 공격자는 시스템을 전복시키는 영리한 방법을 찾았습니다.
예를 들어 Cross-site scripting(XSS)공격은,
의도한 콘텐츠와 함께 악성 코드를 전달하도록 사이트를 속임으로써 동일한 출처 정책을 우회합니다.
브라우저가 페이지에 표시되는 모든 코드를 합법적인 해당 페이지 보안 오리진의 일부로 신뢰하기 때문입니다.
 
XSS Cheat Sheet는 매우 오래되었으나,
공격자가 악성 코드를 주입하여 이 신뢰를 위반하는 데 사용할 수 있는 방법의 대표적인 단면입니다.
공격자가 코드를 삽입하는 데 성공하면 거의 게임이 종료됩니다.
사용자 세션 데이터가 손상되고 비밀로 유지되어야 하는 정보가 나쁜 녀석들에게 유출됩니다.
우리는 가능하다면 이것을 방지하고 싶습니다.
 
이 아티클에서는 콘텐츠 보안 정책(CSP)을 이용해
최신 브라우저 내 XSS 공격의 위험과 영향을 크게 줄일 수 있는 방법을 알아봅니다.

요약

  • 출처 허용 목록(allowlists)을 사용하여 허용되는 항목과 허용되지 않는 항목을 클라이언트에 알립니다.
  • 허용 목록에 대해 어떤 지침;지시문(directives)을 사용할 수 있는지 알아보세요.
  • 지시문 키워드를 배우세요
    • ex) script-src
  • 인라인 코드와 eval()은 기본적으로 유해하다 간주합니다.
  • 정책을 적용하기 전에, 발생한 문제를 서버로 보고합니다. (보고 전용 모드)

출처 허용 목록(Source allowlists)

XSS 공격이 악용하는 문제는 브라우저가
응용 프로그램의 일부인 스크립트와 제3자가 악의적으로 주입한 스크립트를 구별할 수 없다는 것입니다.
예를 들어 Google +1 버튼이
이 페이지의 오리진 컨텍스트에서 https://apis.google.com/js/plusone.js의 코드를 로드하고 실행한다고 가정합니다.
우리는 그 코드를 신뢰하지만
apis.google.com의 코드는 믿음직하고, apis.evil.example.com의 코드는 아마도 그렇지 않다는 것을
브라우저가 스스로 알아낼 것이라고 기대할 수는 없습니다.
 
브라우저는 출처에 관계없이 페이지가 요청하는 모든 코드를 행복하게 다운로드하고 실행합니다.
 
서버가 제공하는 모든 것을 맹목적으로 신뢰하는 대신
CSP는 Content-Security-Policy HTTP 헤더를 정의하여
신뢰할 수 있는 콘텐츠 소스의 허용 목록(allowlist)을 생성하고
해당 소스의 리소스만 실행하거나 렌더링하도록 브라우저에 지시합니다.
공격자가 스크립트를 삽입할 구멍을 찾더라도, 스크립트는 허용 목록(allowlist)과 일치하지 않으므로 실행되지 않습니다.
 
우리는 유효한 코드를 제공하는 apis.google.com을 신뢰하고
우리의 오리진도 신뢰하므로
다음 두 소스 중 하나에서 오는 경우에만 스크립트 실행을 허용하는 정책을 정의해 보겠습니다.
 
오리진과, 구글 api에서 오는 스크립트만 허용하는 정책
Content-Security-Policy: script-src 'self' https://apis.google.com
 
짐작하셨겠지만 script-src는 특정 페이지에 대한 일련의 스크립트 관련 권한을 제어하는 ​​명령입니다.
유효한 스크립트 소스로 'self', 그리고 https://apis.google.com을 지정합니다.
브라우저는 HTTPS를 통해 apis.google.com과 현재 페이지의 출처(origin)에서 JavaScript를 충실히 다운로드하고 실행합니다.
script-src를 통해 브라우저에서 실행할 스크립트를 제한
 
이 정책을 정의하면 브라우저는 다른 소스에서 스크립트를 로드하는 대신 단순히 오류를 발생시킵니다.
영리한 공격자가 사이트에 코드를 삽입하는 데 성공하면 오류 메시지가 표시됩니다.

다양한 리소스에 대한 정책

스크립트 리소스는 가장 명백한 보안 위험입니다.
하지만 CSP는 스크립트 외에도 
페이지가 로드할 수 있는 리소스를 상당히 세부적으로 제어할 수 있는
풍부한 정책 지시문 집합(a rich set of policy directives)을 제공합니다.
이미 script-src를 보았으므로 개념이 명확해야 합니다.
 
리소스 지시문(resource directives)의 나머지를 빠르게 살펴보겠습니다.
아래 목록은 레벨 2의 지시문 스펙을 나타냅니다. level 3 spec이 제안되었으나,
주요 브라우저에서 거의 구현되지 않았습니다.(largely unimplemented)
 
  • base-uri : 페이지의 <base> 요소에 나타날 수 있는 URL을 제한합니다.
  • child-src : worker 및 embedded 프레임 콘텐츠에 대한 URL을 나열합니다. 
    • child-src : https://youtube.com 는 유투부에서 온 동영상을 포함할 수 있으나, 다른 출처의 리소스는 사용할 수 없습니다.
  • connect-src : (XHR, WebSockets 및 EventSource를 통해) 연결할 수 있는 출처를 제한합니다.
  • font-src : 웹 폰트를 제공할 수 있는 출처를 지정합니다.
  • form-action : <form> 태그의 유효한 양식 제출 타겟을 나열합니다.
  • frame-ancestors : 현재 페이지를 포함할 수 있는 소스를 지정합니다.
    • 이 지시문(directive)은 <frame>, <iframe>, <embed> 및 <applet> 태그에 적용됩니다.
    • 이 지시문은 <meta> 태그에서 사용할 수 없으며 HTML이 아닌 리소스에만 적용됩니다.
  • frame-src : 레벨 2에서 더 이상 사용되지 않지만 레벨 3에서 복원됩니다.
    • child-src와 동일합니다.
  • img-src : 이미지를 로드할 수 있는 출처를 정의합니다.
  • media-src : 비디오 및 오디오를 제공할 수 있는 출처를 제한합니다.
  • object-src : Flash 및 기타 플러그인을 제어할 수 있습니다.
  • plugin-types : 페이지가 호출할 수 있는 플러그인의 종류를 제한합니다.
  • report-uri : 콘텐츠 보안 정책을 위반한 경우 브라우저가 보고서를 보낼 URL을 지정합니다.
    • 이 지시문은 <meta> 태그에서 사용할 수 없습니다.
  • style-src : 스타일시의 script-src의 역할을 합니다.
  • upgrade-insecure-requests :
    • 사용자 에이전트에게 HTTP를 HTTPS로 변경하여 URL 체계를 다시 작성하도록 지시합니다.
    • 이 지시문은 재 작성해야 하는 이전 URL이 많은 웹사이트를 위한 것입니다.
  • worker-src :
    • 작업자, 공유 작업자 또는 서비스 작업자로 로드될 수 있는 URL을 제한하는 CSP 레벨 3 지시문 입니다.
    • 2017년 7월 현재 이 지시문은 제한적으로 구현되어 있습니다.(limited implementations)
기본적으로 지시문은 어떤 것도 제한하지 않습니다.
즉, 지시문에 대한 특정 정책을 설정하지 않은 경우,
font-src을 예를 들면
해당 지시문은 기본적으로 *를 유효한 소스로 지정한 것처럼 동작합니다
(제한 없이 어느 출처에서나 글꼴을 로드할 수 있음)
 
default-src 지시문을 지정하여 이 기본 동작을 재정의할 수 있습니다.
이 지시문은 지정하지 않은 대부분의 지시문에 대한 기본값을 정의합니다.
일반적으로 이것은 -src로 끝나는 모든 지시문에 적용됩니다.
default-src가 https://example.com 으로 설정되어 있고
font-src 지시문을 지정하지 못한 경우 https://example.com 에서만 글꼴을 로드할 수 있습니다.
 
이전 예제에서는 script-src만 지정했습니다.
이 경우, 모든 출처에서 이미지, 글꼴 등을 로드할 수 있습니다.
 
반대로 아래 지시문은 default-src를 폴백으로 사용하지 않습니다.
설정하지 않는 것은  무엇이든 허용하는 것과 같습니다.
  • base-uri
  • form-action
  • frame-ancestors
  • plugin-types
  • report-uri
  • sandbox
HTTP 헤더에 각 지시문을 나열하고
지시문을 세미콜론으로 구분하여 특정 응용 프로그램에 적합한 만큼 이러한 지시문을 사용할 수 있습니다.
 
특정 타입의 모든 필수 리소스를 단일 지시문에 나열해야 합니다.
첫 번째 지시문 script-src https://host1.com 을 작성했다면,
두 번째 지시문 script-src https://host2.com 은 무시됩니다.
 
다음과 같은 경우 두 출처를 유효한 것으로 올바르게 지정합니다.
script-src https://host1.com https://host2.com​
예를 들어 콘텐츠 전송 네트워크(예: https://cdn.example.net)의 모든 리소스를 로드하는 애플리케이션이 있고,
프레임 내 콘텐츠나 플러그인이 필요하지 않다는 것을 알고 있다면 정책은 다음과 같을 수 있습니다.
Content-Security-Policy: default-src https://cdn.example.net; child-src 'none'; object-src 'none'

구현 세부사항

웹의 다양한 자습서에서 X-WebKit-CSP 및 X-Content-Security-Policy 헤더를 볼 수 있습니다.
앞으로는 이러한 접두사 헤더를 무시해야 합니다.
최신 브라우저(IE 제외)는 접두사(X)가 없는 Content-Security-Policy 헤더를 지원합니다.
 
사용하는 헤더에 관계없이 정책은 페이지별로 정의됩니다.
보호하려는 모든 응답과 함께 HTTP 헤더를 보내야 합니다.
이것은 특정 요구 사항에 따라 특정 페이지에 대한 정책을 미세 조정할 수 있으므로 많은 유연성을 제공합니다.
아마도 귀하의 사이트에서 한 세트의 페이지에는 +1 버튼이 있고 다른 페이지에는 없을 수 있습니다.
필요한 경우에만 버튼 코드가 ​​로드되도록 허용할 수 있습니다.
 
각 지시문의 출처 목록은 유연합니다.
  • 스킴(data:, https:)별로 출처를 지정할 수 있습니다.
  • 호스트 이름(example.com, 해당 호스트의 모든 출처: 모든 스킴, 모든 포트와 일치)부터 정규화된 URI(https:/ /example.com:443(HTTPS만 일치, example.com만 일치, 포트 443만 일치)까지 구체적으로 지시 가능합니다.
  • 와일드카드는 스키마, 포트 또는 호스트 이름의 가장 왼쪽 위치에서만 허용됩니다.
    • *://*.example.com:*은 example.com의 모든 포트, 모든 스키마, 모든 하위 도메인과 일치하지만, example.com 자체와는 일치하지 않습니다.

출처 목록에는 다음 네 가지 키워드도 허용됩니다.

  • 'none' : 예상할 수 있듯이 아무 것도 일치하지 않습니다.
  • 'self' : 현재 출처와 일치하지만 하위 도메인은 일치하지 않습니다.
  • 'unsafe-inline' : 인라인 JavaScript 및 CSS를 허용합니다.
  • 'unsafe-eval'은 eval과 같은 텍스트 to 자바스크립트 메커니즘을 허용합니다.
이러한 키워드에는 작은 따옴표가 필요합니다.
  • 예를 들어 script-src 'self'(따옴표 포함)는 현재 호스트에서 JavaScript 실행을 승인합니다.
  • script-src self(따옴표 없음)는 "self"라는 이름의 서버(현재 호스트가 아닌)의 JavaScript를 허용합니다.
    • 이는 분명 당신이 원하는 것이 아닐 것입니다.

샌드박싱

유의미한 지시문이 하나 더 있습니다: sandbox 입니다.
지금까지 살펴본 다른 항목과 약간 다릅니다.
페이지가 로드할 수 있는 리소스가 아니라 페이지에서 수행할 수 있는 작업에 제한을 두기 때문입니다.
 
샌드박스 지시문이 있는 경우 페이지는 샌드박스 속성이 있는 <iframe> 내부에 로드된 것처럼 처리됩니다.
이는 페이지에 광범위한 영향을 미칠 수 있습니다.
페이지를 고유한 출처로 강제 지정하고 양식 제출을 방지하는 등의 작업을 수행할 수 있습니다.
이 문서의 범위를 약간 벗어나지만 HTML5 사양의 "샌드박싱" 섹션에서
유효한 샌드박싱 특성에 대한 자세한 내용을 찾을 수 있습니다.

메타 태그

CSP가 선호하는 컨텐트 전달 메커니즘은 HTTP 헤더입니다.
그러나 마크업에서 직접 페이지에 대한 정책을 설정하는 것이 유용할 수 있습니다.
http-equiv 속성과 함께 <meta> 태그를 사용하여 이를 수행할 수 있습니다.

<meta http-equiv="Content-Security-Policy" content="default-src https://cdn.example.net; child-src 'none'; object-src 'none'">

frame-ancestors, report-uri 또는 sandbox에는 사용할 수 없습니다.


인라인 코드는 유해한 것으로 간주됩니다

CSP는 허용 목록 출처를 기반으로 한다는 것이 명확해야 합니다.
이는 특정 리소스 집합을 허용 가능한 것으로 처리하고 나머지는 거부하도록 브라우저에 지시하는 명확한 방법이기 때문입니다.
그러나 출처 기반 허용 목록은 XSS 공격으로 인한 가장 큰 위협인 인라인 스크립트 삽입을 해결하지 못합니다.
공격자가 일부 악성 페이로드(<script>sendMyDataToEvilDotCom()</script>)를 직접 포함하는 스크립트 태그를 삽입할 수 있는 경우
브라우저에는 합법적인 인라인 스크립트 태그와 구별할 수 있는 메커니즘이 없습니다.
CSP는 인라인 스크립트를 완전히 금지하여 이 문제를 해결합니다.
이것이 해당 문제를 해결할 수 있는 유일하며 확실한 방법입니다.
 
이 금지에는 스크립트 태그에 직접 포함된 스크립트뿐만 아니라 인라인 이벤트 핸들러 및 javascript: URL도 포함됩니다.
스크립트 태그의 내용을 외부 파일로 이동하고
javascript: URL 및 <a ... onclick="[JAVASCRIPT]">를 적절한 addEventListener() 호출로 바꿔야 합니다.
 
 
예를 들어 아래의 파일을
<script>
    function doAmazingThings() {
    alert('YOU AM AMAZING!');
    }
</script>
<button onclick='doAmazingThings();'>Am I amazing?</button>
다음과 같이 작성합니다.
<!-- amazing.html -->
<script src='amazing.js'></script>
<button id='amazing'>Am I amazing?</button>
// amazing.js
function doAmazingThings() {
    alert('YOU AM AMAZING!');
}
document.addEventListener('DOMContentLoaded', function () {
    document.getElementById('amazing')
    .addEventListener('click', doAmazingThings);
});
 
재작성된 코드는 CSP와 잘 작동하는 것 외에도 많은 이점이 있습니다.
  • CSP 사용에 관계없이 이미 모범 사례입니다.
    • 인라인 JavaScript는 데이터(마크업) 구조와 동작(기능)을 혼합해서는 안 되는 방식으로 혼합합니다.
  • 외부 리소스는 브라우저가 캐싱하기 쉽고 개발자가 이해하기 쉬우며 컴파일 및 축소에 도움이 됩니다.
  • 코드를 외부 리소스로 옮기는 작업을 수행하면 더 나은 코드를 작성할 수 있습니다(모듈화).

인라인 스타일 또한 같은 방식으로 처리되어야 합니다.

  • 스타일 속성과 스타일 태그는 모두 외부 스타일시트로 통합되어, CSS가 가능하게 하는 놀랍도록 영리한 다양한 데이터 유출 방법(surprisingly clever)으로부터 보호해야 합니다.
인라인 스크립트와 스타일이 있어야 하는 경우
script-src 또는 style-src 지시문에서 허용된 소스로 'unsafe-inline'을 추가하여 활성화할 수 있습니다.
 
nonce나 hash를 사용할 수도 있지만, 사용하면 안 됩니다.
인라인 스크립트 금지는 CSP가 제공하는 가장 큰 보안 승리이며
인라인 스타일 금지는 마찬가지로 애플리케이션을 강화합니다.
모든 코드를 라인 외부로 옮긴 후 기능이 올바르게 작동하는지 확인하기 위해 약간의 노력이 필요하지만 충분히 가치가 있는 절충안입니다.

인라인 스크립를 꼭 사용해야 한다면

CSP 레벨 2는 암호화 nonce(한 번 사용되는 숫자) 또는 해시를 사용해
allowlist에 특정 인라인 스크립트를 추가할 수 있도록 하여 인라인 스크립트에 대한 이전 버전과의 호환성을 제공합니다.

nonce 사용 방법

스크립트 태그에 nonce 속성을 지정합니다.

해당 값은 신뢰할 수 있는 소스 목록의 값과 일치해야 합니다.

예를 들어 다음과 같습니다.

<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
    // Some inline code I can't remove yet, but need to asap.
</script>

이제 nonce- 키워드에 추가된 script-src 지시문에 nonce를 추가합니다.

Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'

nonce는 모든 페이지 요청에 대해 다시 생성되어야 하며 추측할 수 없어야 합니다.

hash 사용 방법

해시는 거의 같은 방식으로 작동합니다.

스크립트 태그에 코드를 추가하는 대신 스크립트 자체의 SHA 해시를 만들어 script-src 지시문에 추가합니다.

예를 들어 페이지에 다음이 포함되어 있다고 가정해 보겠습니다.

<script>alert('Hello, world.');</script>

귀하의 정책에는 다음이 포함됩니다.

Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='
 
여기서 주의할 점이 몇 가지 있습니다.
  • sha*- 접두사는 해시를 생성하는 알고리즘을 지정합니다.
    • 위의 예에서는 sha256-이 사용됩니다. CSP는 sha384- 및 sha512-도 지원합니다.
  • 해시를 생성할 때 <script> 태그를 포함하지 마세요.
    • 또한 선행 또는 후행 공백을 포함하여 대문자 및 공백이 중요합니다.
Google 검색을 통해 SHA 해시 생성에 대한 언어 별 솔루션을 찾을 수 있습니다.
Chrome 40 이상을 사용하면 DevTools를 연 다음 페이지를 다시 로드하면,
콘솔 탭에 각 인라인 스크립트에 대한 올바른 sha256 해시가 포함된 오류 메시지가 포함됩니다.

Eval도 마찬가지 입니다

공격자가 스크립트를 직접 주입할 수 없는 경우에도
응용 프로그램을 속여 비활성 텍스트를 실행 가능한 JavaScript로 변환하고 대신 실행하도록 할 수 있습니다.
eval(), new Function(), setTimeout([string], …) 및 setInterval([string], ...)은
모두 삽입된 텍스트가 예상치 못한 악의적인 작업을 실행할 수 있는 가능성이 있는 함수(벡터)입니다.
이 위험에 대한 CSP의 기본 대응은 이러한 모든 벡터를 완전히 차단하는 것입니다.
 
이는 애플리케이션 구축 방식에 적지 않은 영향을 미칩니다.
  • eval에 의존하지 않고 내장된 JSON.parse를 통해 JSON을 구문 분석해야 합니다.
    • 네이티브 JSON 연산은 IE8 이후 모든 브라우저에서 사용할 수 있으며 완전히 안전합니다.
  • setTimeout 또는 setInterval 호출을 문자열이 아닌 인라인 함수로 다시 작성하세요

예를 들어 아래 함수를

setTimeout("document.querySelector('a').style.display = 'none';", 10);

아래와 같이 재작성합니다.

setTimeout(function () {
    document.querySelector('a').style.display = 'none';
}, 10);

런타임 시 인라인 템플릿 사용 금지:

  • 많은 템플릿 라이브러리는 런타임 시 템플릿 생성 속도를 높이기 위해 new Function()을 자유롭게 사용합니다.
  • 동적 프로그래밍의 멋진 응용이지만 악성 텍스트를 평가할 위험이 있습니다.
  • 일부 프레임워크는 즉시 사용 가능한 CSP를 지원하며 eval이 없는 경우 강력한 파서로 대체됩니다.
그러나 더 나은 선택은 사전 컴파일을 제공하는 템플릿 언어입니다(예: Handlebars).
템플릿을 미리 컴파일하면 가장 빠른 런타임 구현보다 사용자 경험이 더 빨라질 수 있으며 더 안전합니다.
eval 및 text-to-JavaScript 형제가 애플리케이션에 필수적인 경우,
script-src 지시문에서 허용된 소스로 'unsafe-eval'을 추가하여 활성화할 수 있지만 권장하지 않습니다.
문자열 실행 기능을 금지하면 공격자가 사이트에서 승인되지 않은 코드를 실행하기가 훨씬 더 어려워집니다.

보고하기

클라이언트 측에서 신뢰할 수 없는 리소스를 차단하는 CSP의 기능은 사용자에게 큰 도움이 되지만,
일종의 알림을 서버로 다시 전송하여
처음에 악의적인 주입을 허용하는 버그를 식별하고 제거할 수 있도록 하는 것이 상당히 도움이 될 것입니다. 
이를 위해 브라우저가 JSON 형식의 위반 보고서를 report-uri 지시문에 지정된 위치에 게시하도록 지시할 수 있습니다.
Content-Security-Policy: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;
이러한 보고서는 다음과 같이 표시됩니다.
{
    "csp-report": {
    "document-uri": "http://example.org/page.html",
    "referrer": "http://evil.example.com/",
    "blocked-uri": "http://evil.example.com/evil.js",
    "violated-directive": "script-src 'self' https://apis.google.com",
    "original-policy": "script-src 'self' https://apis.google.com; report-uri http://example.org/my_amazing_csp_report_parser"
    }
}
해당 데이터는
위반이 발생한 페이지(document-uri),
해당 페이지의 리퍼러(HTTP 헤더 필드와 달리 키는 맞춤법 오류가 없습니다;referer),
페이지의 정책을 위반한 리소스(blocked-uri),
위반한 특정 지시어(violated-directive),
페이지의 전체 정책(original-policy)을 포함합니다.
 

보고부터 시작하기

CSP를 이제 막 시작했다면 엄격한 정책을 사용자에게 적용하기 전,
애플리케이션의 현재 상태를 평가하는 것이 좋습니다.
완전한 배포를 위한 디딤돌로 브라우저에 정책을 모니터링하도록 요청하여
위반을 보고하지만 제한을 적용하지는 않을 수 있습니다.
Content-Security-Policy 헤더를 보내는 대신
Content-Security-Policy-Report-Only 헤더를 보냅니다.
Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;
보고 전용 모드에서 지정된 정책은 제한된 리소스를 차단하지 않지만 지정한 위치로 위반 보고서를 보냅니다.
두 헤더를 모두 보내서 하나의 정책을 시행하면서 다른 정책을 모니터링할 수도 있습니다.
이것은 애플리케이션의 CSP에 대한 변경의 영향을 평가하는 좋은 방법입니다.
새 정책에 대한 보고를 켜고, 위반 보고서를 모니터링하고, 나타나는 모든 버그를 수정합니다.
효과에 만족하면 새 정책 시행을 시작합니다.

실제 예제로 배우기

CSP 1은 Chrome, Safari 및 Firefox에서 꽤 사용할 수 있지만 IE 10에서는 지원이 매우 제한적입니다.
자세한 스펙은 caniuse.com(view specifics at caniuse.com)에서 볼 수 있습니다.
 
CSP 레벨 2는  Chrome 버전 40부터 사용할 수 있습니다.
Twitter 및 Facebook과 같은 대규모 사이트에서 헤더를 배포했으며(Twitter의 사례 연구(Twitter's case study)를 읽어보세요)
이 표준은 매우 잘 준비되어 있습니다.
 
애플리케이션 정책을 만들기 위한 첫 번째 단계는 실제로 로드하는 리소스를 평가하는 것입니다.
앱에서 항목을 구성하는 방법을 제어할 수 있다고 생각되면 이러한 요구 사항을 기반으로 정책을 설정하십시오.
몇 가지 일반적인 사용 사례를 살펴보고
CSP의 보호 범위 내에서 이를 가장 잘 지원할 수 있는 방법을 결정해 보겠습니다.

사용 사레 #1 : 소셜 미디어 위젯

Facebook의 좋아요 버튼(Like button)에는 다양한 구현 옵션이 있습니다.

사이트의 다른 부분에서 안전하게 샌드박스 처리되므로  <iframe> 을 사용하는 것을 추천합니다.

제대로 작동하려면 child-src https://facebook.com 지시문이 필요합니다.
디폴트로 Facebook에서 제공하는  <iframe>코드는 상대 URL인 //facebook.com을 로드합니다.
명시적으로 HTTPS를 지정하도록 변경합니다: https://facebook.com.
필요하지 않다면 HTTP를 사용할 이유가 없습니다.
 
 

Twitter의 트윗 버튼(Tweet button)은 스크립트 및 프레임에 둘 다 의존합니다.

이 둘은 동일하게 https://platform.twitter.com  호스팅됩니다.
Twitter도 마찬가지로 디폴트로 상대 URL을 제공합니다.

만약 당신의 자바스크립트 파일이

Twitter가 제공하는 JavaScript 스니펫을 참조하고 있다면,
다음과 같이 로컬에서 복사/붙여넣기할 때 HTTPS를 지정하도록 코드를 편집하세요.

script-src https://platform.twitter.com; child-src https://platform.twitter.com

 

다른 플랫폼도 유사한 요구 사항을 갖고 있으며 유사하게 처리할 수 있습니다.

default-src를 'none'으로 설정하고 콘솔을 확인하여
위젯이 작동하도록 활성화해야 하는 리소스를 결정하는 것이 좋습니다.
 
여러 위젯을 포함하는 것은 간단합니다.
단일 타입의 모든 리소스를 단일 지시어로 병합하는 것을 기억하면서 정책 지시문을 결합하기만 하면 됩니다.
세 가지 소셜 미디어 위젯을 모두 원하는 경우 정책은 다음과 같습니다.
script-src https://apis.google.com https://platform.twitter.com; child-src https://plusone.google.com https://facebook.com https://platform.twitter.com

 

사용 사레 #2 : 내 리소스만 허용하기

뱅킹 사이트를 운영하고 있고 직접 작성한 리소스만 로드할 수 있도록 하고 싶다고 잠시 가정해 봅시다.
이 시나리오에서는 모든 것을 차단하는 기본 정책(default-src 'none')으로 시작합니다.
 
은행이 https://cdn.mybank.net의 CDN에서 모든 이미지, 스타일 및 스크립트를 로드하고
XHR을 통해 https://api.mybank.com/에 연결하여 모든 데이터를 가져온다고 가정합니다.
프레임은 사이트의 로컬 페이지에만 사용됩니다. (서드파티 출처 없음)
사이트에는 플래시도, 글꼴도, 추가 기능도 없습니다.
보낼 수 있는 가장 제한적인 CSP 헤더는 다음과 같습니다.
Content-Security-Policy: default-src 'none'; script-src https://cdn.mybank.net; style-src https://cdn.mybank.net; img-src https://cdn.mybank.net; connect-src https://api.mybank.com; child-src 'self'

사용 사레 #3 : SSL만 허용하기

결혼 반지 토론 포럼 관리자는 모든 리소스가 보안 채널을 통해서만 로드되도록 하고 싶지만
스스로 많은 코드를 작성하지는 않습니다.
인라인 스크립트와 스타일로 가득 찬 타사 포럼 소프트웨어의 많은 부분을 재작성하는 것은 그의 능력 밖의 일입니다.
다음 정책이 유효합니다.
Content-Security-Policy: default-src https:; script-src https: 'unsafe-inline'; style-src https: 'unsafe-inline'

https:가 default-src에 지정되어 있어도 스크립트 및 스타일 지시문은 해당 출처를 자동으로 상속하지 않습니다.
각 지시문은 특정 타입의 리소스에 대한 기본값을 완전히 덮어씁니다.


CSP의 미래

content security policy level2는 권고 사항(Recommendation)입니다.
현재 Content Security Policy Level 3 에 대한 작업이 진행 중입니다.


참고

https://web.dev/sandboxed-iframes/ 

 

Play safely in sandboxed IFrames

 

web.dev

https://ko.javascript.info/server-sent-events

 

Server Sent Events

 

ko.javascript.info

 

 

반응형