CSP(Content Security Policy) 적용기

2026.01.19 10:31 · 조회 6

웹취약 점검사이트에서 점수는 무시하고 넘어갔는데

천천히 보니 보안상에도 문제가 있을 것 같아 CSP설정을 nginx와 php내부에서 하게되었다.


웹 보안 점검(SecurityHeaders, CSP 검사 사이트 등)을 돌리다 보면 CSP(Content Security Policy) 항목에서 자주 감점을 맞는다.

  • CSP가 없다
  • CSP가 unsafe-inline을 사용하고 있다
  • CSP 헤더를 파싱할 수 없다

처음에는 “점수 문제 아닌가?” 싶었지만, 실제로 적용해보니 서비스를 깨뜨리지 않고 CSP를 제대로 적용하는 건 생각보다 까다로웠다.


시작은 Report-Only

처음에는 nginx에 아래처럼 Report-Only로 CSP를 걸었다.

add_header Content-Security-Policy-Report-Only "
default-src 'self';
base-uri 'self';
object-src 'none';
frame-ancestors 'self';
form-action 'self';
" always;

  • 차단은 안 함
  • 콘솔/리포트로 위반만 확인
  • 이 상태는 “CSP를 테스트 중”이지, 방어라고 부르긴 어렵다.


CDN 사용으로 인한 첫 번째 벽

  • https://cdn.jsdelivr.net는 다음 CDN을 사용 중이었다.
  • 그래서 CSP를 실제로 적용하려면 명시적 허용이 필요했다.
script-src 'self' https://cdn.jsdelivr.net;;
style-src  'self' https://cdn.jsdelivr.net;;


Enforcement로 전환 → 사이트 꺠짐 현상

Report-Only를 Content-Security-Policy로 바꾸자마자:

  • CSS 깨짐
  • 클릭 안 됨
  • 이미지 안 나옴

원인:

  • 인라인 <style> 차단
  • 인라인 <script> / onclick 차단


unsafe-inline의 유혹 (그리고 감점)

급한 복구용으로 아래처럼 풀면 사이트는 정상 동작한다.

script-src 'self' https://cdn.jsdelivr.net 'unsafe-inline';
style-src  'self' https://cdn.jsdelivr.net 'unsafe-inline';

하지만 보안 검사 사이트에서는 바로 감점:

Content Security Policy implemented unsafely(unsafe-inline 사용)

이건 점수 문제만이 아니라, XSS 방어력이 실제로 떨어진다.


결론: nonce 방식이 정답

unsafe-inline 없이 인라인 코드를 살리는 유일한 현실적인 방법은 nonce 방식이다.

PHP에서 nonce 생성 + CSP 헤더/인라인 코드에 nonce 적용

$csp_nonce = base64_encode(random_bytes(16));

$csp = "default-src 'self'; "
     . "base-uri 'self'; "
     . "object-src 'none'; "
     . "frame-ancestors 'self'; "
     . "form-action 'self'; "
     . "script-src 'self' https://cdn.jsdelivr.net 'nonce-{$csp_nonce}'; "
     . "style-src 'self' https://cdn.jsdelivr.net 'nonce-{$csp_nonce}'; "
     . "img-src 'self' https://cdn.jsdelivr.net data: blob:; "
     . "font-src 'self' https://cdn.jsdelivr.net data:; "
     . "connect-src 'self'; "
     . "upgrade-insecure-requests";

header("Content-Security-Policy: {$csp}");
<style nonce="<?= htmlspecialchars($csp_nonce) ?>">
  /* 기존 CSS 그대로 */
</style>
<script nonce="<?= htmlspecialchars($csp_nonce) ?>">
  // 기존 JS 그대로
</script>

나름 모든 부분이 해결된 듯 하다.

  • 사이트 정상 동작
  • unsafe-inline 제거
  • CSP 검사 감점 사라짐
  • XSS 주입 난이도 대폭 상승


CSP는 “헤더 하나 추가하면 끝”인 기능이 아니다.

  • Report-Only → Enforcement
  • unsafe-inline → nonce
  • 점수보다 실제 방어 구조

이 과정을 거쳐야 비로소 “CSP를 적용했다”고 말할 수 있다.


한 줄 요약

CSP는 점수를 위한 설정이 아니라 XSS가 터졌을 때 피해를 줄이기 위한 최후의 안전벨트다.

댓글 0

아직 댓글이 없습니다.