본문으로 건너뛰기
김신건의 로그

[Django 6.0] Content Security Policy: XSS 방어의 최종형

· 수정 · 📖 약 1분 · 503자/단어 #django #csp #security #xss #django-6
Django CSP, Content Security Policy, django csp middleware, csp-report-only, CSP nonce

정의

Content Security Policy (CSP) = 브라우저에게 어떤 스크립트/스타일/이미지 만 허용 할지 선언. XSS 공격의 마지막 방어선.

Django 6.0 부터 CSP 지원이 내장 (옛 django-csp 서드파티 → Django 표준). 자세한 XSS 는 django-security 참고.

목적 + 대안

접근의미
입력 필터링사용자 입력에서 <script> 제거 (완벽하지 않음)
출력 escape{% autoescape %} 로 HTML escape (Django 기본)
CSP브라우저에게 인라인 스크립트 실행 금지 지시

IMPORTANT

CSP 는 다중 방어 의 하나. Escape + Sanitize + CSP 3중 방어가 정통.

CSP Header 구조

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://cdn.example.com;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  connect-src 'self' https://api.example.com;
  frame-ancestors 'none';
  report-uri /csp-report/
Directive의미
default-src기본값
script-srcJavaScript 허용 원본
style-srcCSS
img-src이미지
connect-srcfetch, XHR, WebSocket
font-src폰트
frame-src / frame-ancestorsiframe
form-actionform action target
report-uri위반 리포트

Django 6.0 CSP 설정

# settings.py
MIDDLEWARE = [
    ...
    'django.middleware.csp.ContentSecurityPolicyMiddleware',
]

SECURE_CSP = {
    'default-src': ["'self'"],
    'script-src': ["'self'", 'https://cdn.example.com'],
    'style-src': ["'self'", "'unsafe-inline'"],
    'img-src': ["'self'", 'data:', 'https:'],
    'connect-src': ["'self'", 'https://api.example.com'],
    'frame-ancestors': ["'none'"],
    'report-uri': ['/csp-report/'],
}

Report-Only 모드 (안전한 배포)

# 처음 도입 시 report-only 로 시작
SECURE_CSP_REPORT_ONLY = {
    'default-src': ["'self'"],
    'script-src': ["'self'"],
    'report-uri': ['/csp-report/'],
}

브라우저가 위반 감지 시 report 만 전송, 실제 차단 안 함. 로그 분석 후 정식 정책으로 전환.

Nonce 로 인라인 스크립트 허용

# views.py
from django.middleware.csp import get_csp_nonce

def home(request):
    return render(request, 'home.html', {
        'csp_nonce': get_csp_nonce(request),
    })
<script nonce="{{ csp_nonce }}">
  console.log('inline script allowed');
</script>

Header:

Content-Security-Policy: script-src 'self' 'nonce-xyz123abc';

TIP

동적 인라인 스크립트 를 안전하게. 'unsafe-inline' 보다 훨씬 안전.

Hash (정적 인라인)

SECURE_CSP = {
    'script-src': [
        "'self'",
        "'sha256-B2yPHKaXnvFWtRChIbabYmUBFZdVfKKXHbWtWidDVF8='",
    ],
}

특정 인라인 스크립트 hash 계산 후 허용. Nonce 와 달리 정적 스크립트만.

위반 리포트 처리

# views.py
import json
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def csp_report(request):
    if request.method == 'POST':
        report = json.loads(request.body)
        logger.warning('CSP violation: %s', report)
        return HttpResponse(status=204)
{
  "csp-report": {
    "document-uri": "https://example.com/page/",
    "referrer": "",
    "violated-directive": "script-src 'self'",
    "blocked-uri": "https://evil.com/xss.js",
    "line-number": 42
  }
}

Strict CSP (현대 권장)

Google 이 권장하는 strict CSP:

SECURE_CSP = {
    'script-src': ["'strict-dynamic'", "'nonce-{{nonce}}'"],
    'object-src': ["'none'"],
    'base-uri': ["'none'"],
}
  • strict-dynamic: nonce 통과한 스크립트가 로드한 자원은 자동 허용.
  • object-src 'none': Flash/plugin 완전 차단.

흔한 함정

WARNING

  1. unsafe-inline 남발 = CSP 의 의미 없음. Nonce 또는 hash 사용.
  2. CDN URL 하드코딩 = CDN 변경 시 앱 다운. 설정 관리.
  3. report-uri 없이 시작 = 위반 파악 못함. 반드시 report 먼저.
  4. 'unsafe-eval' 필요 = React 개발 mode 등. Production 은 build 후 제거.

다른 프레임워크

FrameworkCSP 지원
Django 6.0+내장
Django 5.x 이하django-csp 서드파티
RailsRails 5.2+ 내장 (config.content_security_policy)
SpringSpring Security header
Expresshelmet.js
Next.jsnext.config.js headers

관련 위키

이 글의 용어 (4개)
[Auth] CSRF: 위조 요청 공격과 방어auth-security
정의 CSRF (Cross-Site Request Forgery) 는 사용자가 로그인된 상태 에서 공격자가 만든 페이지 가 피해자 브라우저로 위조 요청 을 보내는 공격. 쿠키 기…
[Django] 보안: CSRF, XSS, SQL injection, headersdjango
정의 Django는 OWASP Top 10 대부분을 기본 방어한다: CSRF 토큰, ORM의 SQL 인젝션 방지, 템플릿 자동 escape, 비밀번호 해싱, 세션 쿠키 보안 등.…
[Django] Middleware: 요청/응답 가로채기django
정의 Middleware는 모든 요청/응답을 가로채는 체인 구조 처리기. 요청은 위 → 아래, 응답은 아래 → 위로 흐른다. 인증, 세션, CSRF, gzip 압축, 보안 헤더 …
[Network] CORS: Same-Origin Policy, preflight, credentialsnetwork
정의 CORS (Cross-Origin Resource Sharing) 는 Same-Origin Policy (SOP) 의 완화 메커니즘. 브라우저가 origin 이 다른 리소스…

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기