제공 서비스
웹 보안 점검 소스코드 분석 (SAST) 외부 공격표면 진단 (EASM)
요금제 스토어 블로그 파트너 마이페이지 무료 보안 점검
웹 보안 2026.05.15 · 조회 220

CSP nonce 잘못 구현 — XSS 후방어가 무력화되는 5가지 패턴 [2026]

Content Security Policy의 nonce는 XSS 후방어의 핵심이지만, 70% 이상의 SaaS가 정적 nonce·예측 가능한 nonce·strict-dynamic 누락으로 우회 가능한 상태다. 표준 구현 코드와 5가지 자주 발생하는 실수를 정리했다.

CSP nonce는 매 요청마다 새로 생성되는 일회용 토큰으로, 인라인 스크립트가 진짜 서버에서 나온 코드인지 증명하는 XSS 후방어 메커니즘이다.
공격자가 입력값으로 XSS를 주입해도 nonce를 모르면 브라우저가 차단하지만, 정적 nonce·약한 난수·strict-dynamic 누락 같은 잘못된 구현은 후방어를 무력화한다.
이 글은 5가지 실수 패턴, Django 표준 미들웨어 코드, 30초 자가진단을 정리했다.

한눈에 보는 CSP nonce

Q. nonce는 어떻게 XSS를 막나요? A. 브라우저는 CSP 헤더의 nonce 값과 일치하는 script 태그만 실행합니다. 공격자가 주입한 인라인 스크립트는 서버 nonce를 모르기 때문에 차단됩니다. Q. 정적 nonce는 왜 위험한가요? A. 매 요청마다 변경되지 않으면 공격자가 한 번만 nonce를 알아내면 모든 사용자 세션에서 XSS 주입이 가능합니다. 매 응답마다 32바이트 이상 난수로 생성해야 합니다. Q. strict-dynamic은 왜 필요한가요? A. nonce가 부여된 스크립트가 동적으로 로드하는 추가 스크립트도 신뢰 체인으로 자동 허용합니다. 누락 시 React/Vue 같은 SPA가 깨지거나 unsafe-inline 우회 패턴이 생깁니다. Q. report-only 모드로 충분한가요? A. report-only는 차단 없이 위반만 보고합니다. 운영에서는 실제 차단(Content-Security-Policy)으로 전환해야 방어가 동작합니다.

5가지 자주 발생하는 실수 패턴

#패턴위험도
1nonce를 매 요청 새로 생성하지 않음 (정적 또는 세션당 1회)치명
2난수 엔트로피 부족 (Math.random, 짧은 hex)치명
3strict-dynamic 누락 → 동적 스크립트 차단 회피 위해 unsafe-inline 추가치명
4report-only 모드로만 운영, 실제 차단 미적용높음
5script-src에 'self' + https: 광역 허용으로 nonce 무력화높음

Django 표준 미들웨어 구현

import secrets
from django.utils.deprecation import MiddlewareMixin

class CSPNonceMiddleware(MiddlewareMixin):
    def process_request(self, request):
        # 매 요청 새 nonce — 32바이트 = 256bit 엔트로피
        request.csp_nonce = secrets.token_urlsafe(32)

    def process_response(self, request, response):
        nonce = getattr(request, 'csp_nonce', '')
        csp = (
            f"default-src 'self'; "
            f"script-src 'nonce-{nonce}' 'strict-dynamic' https:; "
            f"object-src 'none'; base-uri 'self';"
        )
        response.headers['Content-Security-Policy'] = csp
        return response

# 템플릿: <script nonce="{{ request.csp_nonce }}">...</script>

핵심 4요소: (1) 매 요청 새 nonce (2) secrets 모듈 사용 (3) strict-dynamic 포함 (4) object-src 'none'.
hashlib.md5나 random 모듈은 예측 가능해 사용 금지다.
unsafe-inline·unsafe-eval은 nonce 사용 시 무시되지만, 광역 허용은 다른 우회를 만든다.

지금 1분만 — CodeScan 무료 스캔에 자기 도메인을 입력하면 CSP 헤더 + 8종 보안 헤더를 자동 점검합니다.

30초 자가진단

# CSP 헤더 존재 확인
curl -I https://yourdomain.com | grep -i "content-security-policy"

# nonce가 매번 바뀌는지 — 2회 호출 후 nonce 값 비교
for i in 1 2; do curl -s https://yourdomain.com | grep -oE 'nonce="[^"]+"' | head -1; done

nonce 값이 동일하면 정적 nonce 결함이다. OWASP A03: Injection 범주에 해당한다.

24시간 패치 절차

순위조치
1secrets.token_urlsafe(32)로 nonce 미들웨어 작성
2script-src에 'nonce-{nonce}' 'strict-dynamic' 적용, unsafe-inline 제거
3모든 인라인 script 태그에 nonce 속성 부착
4report-uri 또는 report-to로 위반 모니터링 추가
5CSP 보고서 1주일 관찰 후 차단 모드 전환

지금 해야 할 것

실무자: CodeScan 무료 스캔으로 CSP + 보안 헤더 자동 점검.
CISO·임원: XSS 후방어 전체 점검은 SENTRIX 30분 1:1 상담.
CSP 도입은 단계적 적용이 필수다.

관련 글

{"@context":"https://schema.org","@type":"FAQPage","mainEntity":[ {"@type":"Question","name":"nonce는 어떻게 XSS를 막나요?","acceptedAnswer":{"@type":"Answer","text":"브라우저는 CSP 헤더의 nonce 값과 일치하는 script 태그만 실행합니다. 공격자가 주입한 인라인 스크립트는 서버 nonce를 모르기 때문에 차단됩니다."}}, {"@type":"Question","name":"정적 nonce는 왜 위험한가요?","acceptedAnswer":{"@type":"Answer","text":"매 요청마다 변경되지 않으면 공격자가 한 번만 nonce를 알아내면 모든 사용자 세션에서 XSS 주입이 가능합니다."}}, {"@type":"Question","name":"strict-dynamic은 왜 필요한가요?","acceptedAnswer":{"@type":"Answer","text":"nonce가 부여된 스크립트가 동적으로 로드하는 추가 스크립트도 신뢰 체인으로 자동 허용합니다."}} ]}
CSP Content Security Policy nonce XSS 방어 보안 헤더 OWASP A03

내 사이트도 점검해보세요

CodeScan으로 보안 취약점을 무료로 점검할 수 있습니다.

무료 스캔 시작하기 →
🛒
추천 상품
웹서비스 런칭 전 보안 세팅
런칭 전에 반드시 해야 하는 보안 설정을 원격으로 직접 해드립니다. HTTPS, 환경변수 분리, 보안 헤더…
220,000원 150,000원

🔒 바이브코딩 보안 체크리스트 받기

바이브코딩 보안 체크리스트(PDF)를 무료로 받아보세요.