CSP - Content Security Policy 기본
Content Security Policy (CSP - 컨텐츠 보안 정책)는 XSS나 데이터를 삽입하는 등의
공격이 발생하였을 때 피해를 줄이고 웹 관리자가 공격 시도를 보고 받을 수 있도록 새롭게 추가된 보안 계층이다.
xss 공격은 브라우저가 서버로부터 전달받은 컨텐츠를 신뢰한다는 점을 이용한다.
그 컨텐츠가 원래 서버에서 추가된 것이 아닌 공격자에 의하여 추가된 컨텐츠라도 그러하다.
CSP는 이를 방지하기 위해 웹 페이지에 사용될 수 있는 자원의 위치 출처 등에 제약을 걸 수 있다.
따라서 공격자가 웹 사이트에 본래 있지 않던 스크립트를 삽입하거나 공격자에게 권한이 있는
서버 등에 요청을 보내지 못하도록 막을 수 있다.
CSP는 XSS 공격의 피해를 완전히 무력화하기 위한 수단은 아니므로 XSS에 대한 자체적인 방어가 병행되어야한다.
CSP 헤더는 1개 이상의 정책 지시문이 세미콜런으로 분리된 형태로 이루어져 있다.
정책 지시문은 지시문(default-src, script-src 등)과 1개 이상의 출처('self', 'https' 등)가
분리된 형태로 지정되어야 한다.
다음은 페이지 내부의 자원들이 같은 오리진 혹은 https://example.test.io에서만 로드되어야 함을 나타내는 예시 CSP 구문이다.
*같거나 특정 오리진을 명시한 CSP 구문
default-src 'self' https://example.test.io
다음과 같이 CSP 구문은 일반적으로 Content-Security-Policy HTTP 헤더에 추가하여 적용할 수 있다. 해당 구문에서 policy-directive 부분에 CSP를 정의하는 정책 디렉티브를 작성한다.
*Content-Security-Policy 예시
Content-Security-Policy: <policy-directive>; <policy-directive>
HTTP 헤더를 이용해 페이지 내부의 자원들이 같은 오리진 혹은 https://example.test.io에서만 로드되어야 함을 나타내는 예시 CSP 헤더는 다음과 같다.
*Content-Security-Policy를 적용한 예시
Content-Security-Policy: default-src 'self' https://example.test.io
CSP 헤더는 HTTP 헤더 외에 meta 태그의 엘리먼트로도 정의할 수 있다.
위의 CSP를 meta 태그로 정의하면 다음과 같이 정의할 수 있다
*meta 태그로 정의한 모습
<meta http-equiv="Content-Security-Policy" content="default-src 'self' https://example.test.io">
- 인라인 코드
CSP는 인라인 코드를 유해하다고 간주한다. 따라서 CSP를 사용할 때에는 기본적으로 인라인 코드를 사용할 수 없다.
인라인 코드란 태그의 src 속성같이 코드를 로드하지 않고 태그 내에 직접 삽입하는 것을 의미한다.
예를 들어 <script>alert(1);</script> 는 <script> 태그 내에 코드를 직접 삽입했기 때문에 인라인 코드이다.
CSP는 인라인 코드 형태를 지양하고 <script src="alert.js"></script> 와 같이
src 속성에 코드 경로를 정의하는 방식을 권장한다.
CSP는 <script> 태그 내에 코드를 삽입하는 것을 포함하여 on* 이벤트 핸들러 속성, javascript: URL 스킵 또한 인라인 코드로 간주하고 허용하지 않는다.
-EVAL
CSP는 기본적으로 문자열 텍스트를 실행 가능한 자바스크립트 코드 형태로 변환하는 메커니즘 또한 유해하다고 간주한다
eval함수가 그러한데 eval과 같이 문자열로부터 코드를 실행하는 경우 의도와 다르게
XSS 공격을 통해 삽입된 공격 코드로 변조되어 실행될 가능성이 있기 때문에 권장하지 않는다.
eval, new Function(), setTimeout([string], ...), setInterval([string], ...) 과 같이 문자열 형태로 입력을 받는 함수의 실행은 모두 차단된다. 다만 해당 함수에 문자열 입력이 아닌 인라인 함수 형태로 파라미터가 전달 될 때에는 차단되지 않는다.
차단
setTimeout("alert(1)", ...)
허용
setTimeout(function(){alert(1)}, ...)
-Policy-directive
<Policy-directive>는 <directive> <value> 형태로 구성된다. <directive>는 지시문이라고 부르며
지시문은 컨텐츠 내에서 로드하는 리소스를 세분화해 어떤 리소스에 대한 출처를 제어할지 결정한다.
<value> 부분에는 <directive>에서 정의한 리소스의 출처를 정의한다.
<value> 에는 여러 개의 출처가 정의될 수 있으며, 공백을 통해 구분된다.
default-src | -src로 끝나는 모든 리소스의 기본 동작을 제어합니다. 만약 CSP 구문 내에서 지정하지 않은 지시문이 존재한다면 default-src의 정의를 따라갑니다. |
img-src | 이미지를 로드할 수 있는 출처를 제어합니다. |
script-src | 스크립트 태그 관련 권한과 출처를 제어합니다. |
style-src | 스타일시트 관련 권한과 출처를 제어합니다. |
child-src | 페이지 내에 삽입된 프레임 컨텐츠에 대한 출처를 제어합니다. |
base-uri | 페이지의 <base> 태그에 나타날 수 있는 URL을 제어합니다. |
*://example.com | 출처의 scheme은 와일드카드를 이용해 표현할 수 있습니다. |
https://*.example.com | 출처의 호스트 서브도메인은 와일드카드를 이용해 표현할 수 있습니다. (단, 와일드카드는 호스트의 중간에 들어갈 수 없습니다. i.e) https://www.*.com, https://*.example.* 또한 서브도메인을 와일드카드로 표현할 시, 서브도메인이 붙어있지 않는 도메인은 포함되지 않습니다. i.e) https://*.example.com으로 출처를 표기할 경우, https://example.com은 포함 안됨 |
https://example.com:* | 출처의 포트는 와일드카드를 이용해 표현할 수 있습니다. |
none | 모든 출처를 허용하지 않습니다. |
self | 페이지의 현재 출처 (Origin) 내에서 로드하는 리소스만 허용합니다. |
unsafe-inline | 예외적으로 인라인 코드의 사용을 허용합니다. |
unsafe-eval | 예외적으로 eval과 같은 텍스트-자바스크립트 변환 메커니즘의 사용을 허용합니다. |
nonce-<base64-value> | nonce 속성을 설정하여 예외적으로 인라인 코드를 사용합니다. <base64-value> 는 반드시 요청마다 다른 난수 값으로 설정해야 합니다. 해당 출처를 설정하면 unsafe-inline 은 무시됩니다. |
<hash-algorithm>-<base64-value> | script 혹은 style 태그 내 코드의 해시를 표현합니다. 해당 출처를 설정하면 unsafe-inline 은 무시됩니다. |