콘텐츠 보안 정책 (CSP)
CSP (Content-Security-Policy) :
이 정책은 Mozilla가 개발 한 표준으로, 실행 시점 인 브라우저에서 XSS (Cross Site Scripting) 공격을 막는 것을 목표로합니다.
CSP는 인라인 스크립트를 금지하는것을 요구합니다. 다만 꼭 사용해야한다면 nonce 를 사용하여 특정 스크립트를 허용해 사용 가능합니다.
CSP는 FACEBOOK, 트위터, 깃허브, 인스타그램 등 다양한 서비스에서 사용중입니다.
CSP 관련해서 여기를 참고해주세요.
이 정책은 Mozilla가 개발 한 표준으로, 실행 시점 인 브라우저에서 XSS (Cross Site Scripting) 공격을 막는 것을 목표로합니다.
CSP는 인라인 스크립트를 금지하는것을 요구합니다. 다만 꼭 사용해야한다면 nonce 를 사용하여 특정 스크립트를 허용해 사용 가능합니다.
CSP는 FACEBOOK, 트위터, 깃허브, 인스타그램 등 다양한 서비스에서 사용중입니다.
CSP 관련해서 여기를 참고해주세요.
CSP 지시문 및 옵션
지시문 | 설명 |
---|---|
default-src | 디폴트 설정 |
connect-src | 연결할 수 있는 URL을 제한 (ajax, websockets 등) |
script-src | 스크립트 관련 권한 집합을 제어 |
child-src | iframe 태그에서 사용 |
style-src | 스타일시트 관련 권한 집합을 제어 |
font-src | 웹 글꼴을 제공할 수 있는 출처를 지정 |
img-src | 이미지 관련 권한 집합을 제어 |
report-uri | 콘텐츠 보안 정책 위반 시 브라우저가 보고서를 보낼 URL을 지정 meta 태그에서는 이 지시문을 사용할 수 없음 |
모든 지시문을 넣지 않았습니다. 나머지 옵션 및 설명은 여기를 참고해주세요. |
src 옵션 설정
- http://www.test.com,example.com, example.com:443 ... 접근 허용 도메인
- 'none'은 모든것을 차단(잠금)
- 'self' 는 현재 도메인만 허용
- 'unsafe-inline'은 소스코드 내 인라인 자바스크립트 및 CSS를 허용
- 'nonce-암호화된문자'은 인라인 자바스크립트 및 CSS를 허용 (아래에서 설명)
CSP 설정방법
1. meta 태그 설정
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self'; ">
<?php $headerCSP = "Content-Security-Policy:". "default-src 'self';". // 기본은 자기 도메인만 허용 "connect-src 'self' ;". // ajax url은 자기 도메인만 허용 "script-src 'self' example.com code.jquery.com https://ssl.google-analytics.com ;". // 자기자신, 접근허용 도메인 설정 "style-src 'self' 'unsafe-inline';"; "report-uri https://example.com/csp_report.php;". // 보안 정책 오류 레포트 URL 지정(meta 태그에선 사용불가) header($headerCSP); ?>
<script src='www.example.com/js/script.js'></script> <!-- 사용가능(접근허용도메인) --> <script src='https://ssl.google-analytics.com/js/script.js'></script> <!-- 사용가능 (접근허용도메인) --> <script src='/js/script.js'></script> <!-- 사용가능 (self) --> <script src='www.test.com/js/script.js'></script> <!-- 사용 불가능 (허용되지 않은 도메인) --> <script>alert('인라인스크립트 허용안함');</script> <!-- 사용 불가능 (인라인 스크립트) --> <link rel="stylesheet" href="/css/common.css"> <!-- 사용가능 (self) --> <span style='color:green;'>인라인스크립트 허용</span'> <!-- 사용가능 (unsafe-inline) --> <link rel="stylesheet" href="https://cdn.metroui.org.ua/v4/css/metro-all.min.css"> <!-- 사용 불가능 (허용되지 않은 도메인) -->
CSP 보안위반 REPORT 설정방법
보안 정책에 위반되었을 경우 아래 와 같이 console.log에 오류 정보 노출
해당 오류 정보는 report-uri 설정을 통해 리포트로 받을수 있음. ("report-uri https://example.com/csp_report.php;")
![](http://192.168.200.157/sim/img/log.png)
csp_report.php 파일 소스 코드
<?php $postdata = file_get_contents("php://input"); $data = json_decode(trim($postdata), true); $log = "================ CSP REPORT 로그 파일 (".date('Y-m-d H:i:s').") =============\n"; $fp = fopen('/var/www/html/sim/log/csp_log.txt', 'a'); fwrite($fp, $log); fwrite($fp, var_export($data, true)."\n"); fclose($fp); ?>
csp_log.txt
================ CSP REPORT 로그 파일 (2018-04-18 20:49:25) ============= array ( 'csp-report' => array ( 'document-uri' => 'http://192.168.200.157/sim/', 'referrer' => '', 'violated-directive' => 'img-src', 'effective-directive' => 'img-src', 'original-policy' => 'connect-src \'self\' ;default-src \'self\';frame-ancestors \'self\' ;frame-src \'none\';media-src \'self\' *.example.com;object-src \'none\'; report-uri http://192.168.200.157/sim/csp_report.php;script-src \'self\' \'unsafe-inline\' example.com code.jquery.com https://ssl.google-analytics.com ;style-src \'self\' \'unsafe-inline\';', 'disposition' => 'enforce', 'blocked-uri' => 'data', 'status-code' => 200, 'script-sample' => '', ), )
document-uri | 위반이 발생한 페이지 |
---|---|
original-policy | CSP 전체 정책 |
violated-directive | 위반한 특정 지시문 |
blocked-uri | 정책을 위반한 리소스 |
CSP 자바스크립트 NONCE 설정
unsafe-inline 옵션을 사용하면 인라인 스크립트를 사용가능하지만, nonce 옵션을 사용하여 좀더 보안에 강화 할수 있음.
nonce-sha256으로 지정된 랜덤한 값을 설정하는것이 좋다. ex) $nonce_key = hash('sha256', microtime()); => nonce-<?=$nonce_key?>
nonce-sha256으로 지정된 랜덤한 값을 설정하는것이 좋다. ex) $nonce_key = hash('sha256', microtime()); => nonce-<?=$nonce_key?>
Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'
<script nonce=EDNnf03nceIOfn39fn3e9h3sdfa> alert('해당 스크립트는 사용가능 한 인라인 스크립트 입니다.'); </script> <script> alert('해당 스크립트는 사용 불가능한 인라인 스크립트 입니다.'); </script>