프레임워크별
Django 보안 — 프로덕션 하드닝 실무 레퍼런스
Django 프로덕션 하드닝 실무 레퍼런스. 우선순위 체크리스트에 더해 DEBUG/ALLOWED_HOSTS·SECRET_KEY·pip CVE·프로덕션 보안 설정·인가·인젝션·SSRF까지. 방어 중심, 공격 절차 없음.
대상: Django로 앱을 운영하는 사람. 여기서는 공격 절차를 다루지 않고, 프로덕션을 굳히기 위한 실무 레퍼런스(우선순위 체크리스트·영역별 대책·자기 검증)를 제시합니다. 프레임워크 전체의 관점은 프레임워크별 보안의 입구도 참조하세요.
우선순위 하드닝 체크리스트
먼저 이 표를 위에서부터 실시합니다. P0은 전제, P1이 가장 빈번한 사고원, P2는 지속적인 운영 위생입니다.
P0 ── 전제(먼저 이것)
DEBUG=False+ALLOWED_HOSTS / SECRET_KEY를 외부화 / pip 의존성 CVE 즉시 패치
P1 ── 가장 빈번한 사고원
프로덕션 보안 설정(SSL/HSTS/Cookie) / 인가(소유자 스코프)
P2 ── 운영 위생
인젝션과 출력 / CSRF·세션·admin / SSRF·업로드
| 우선순위 | 대책 | 구체(Django) |
|---|---|---|
| P0 | DEBUG/ALLOWED_HOSTS | 프로덕션 DEBUG=False+ALLOWED_HOSTS 설정. 상세 오류를 노출하지 않기 |
| P0 | SECRET_KEY | 코드/리포지토리가 아닌 환경에서. 누출 시 로테이션 |
| P0 | pip 의존성 CVE | pip-audit / osv-scanner로 모니터링·실가동 버전으로 판정해 즉시 패치 |
| P1 | 프로덕션 보안 설정 | SECURE_SSL_REDIRECT·SECURE_HSTS_SECONDS·SESSION_COOKIE_SECURE·CSRF_COOKIE_SECURE·SECURE_CONTENT_TYPE_NOSNIFF |
| P1 | 인가를 명시 | 로그인 필수+권한+filter(user=request.user)로 소유자 스코프 |
| P2 | 인젝션/출력 | ORM으로 바인드. raw()/extra() 결합을 피하기. mark_safe/` |
| P2 | CSRF/세션/admin | CSRF(기본값)를 비활성화하지 않기. admin의 노출을 좁히기 |
| P2 | SSRF/업로드 | 서버 측 취득은 허용 리스트로 한정+내부 IP 차단. 업로드 검증+공개면 밖에 저장 |
1. DEBUG와 ALLOWED_HOSTS (P0)
- 프로덕션에서는 **
DEBUG=False**를 확실히 합니다. 활성화되면 오류 화면에 설정·환경 변수·스택 트레이스가 노출되어, 고의의 오류로 뽑힐 수 있습니다. - **
ALLOWED_HOSTS**를 올바르게 설정해 예상 밖 호스트에서의 동작을 방지합니다. 상세 오류의 외부 노출을 막습니다.
2. SECRET_KEY (P0)
- **
SECRET_KEY**는 서명된 Cookie·세션·CSRF 토큰·비밀번호 재설정의 토대입니다. 환경 변수나 시크릿 매니저에서 읽어 들이고, 코드/리포지토리에 쓰지 않습니다. - 누출되면 신속히 로테이션합니다. 공개 디렉터리나 DEBUG 화면에서 노출되지 않게 합니다(→ 공개 디렉터리에 시크릿을 두지 않기).
3. pip 의존성의 CVE (P0)
- pip-audit나 osv-scanner로 알려진 CVE를 기계 모니터링하고, 실가동 버전으로 판정해 즉시 패치합니다(→ 의존성 CVE 모니터링 · 취약점 대응 실무).
- Django와 Python을 지원 대상 버전으로 유지하고, EOL 버전을 방치하지 않습니다.
4. 프로덕션 보안 설정 (P1)
Django는 SecurityMiddleware 경유로 많은 방어를 설정할 수 있습니다. 프로덕션에 맞게 다음을 설정합니다.
SECURE_SSL_REDIRECT(HTTPS 강제) ·SECURE_HSTS_SECONDS(+INCLUDE_SUBDOMAINS/PRELOAD)SESSION_COOKIE_SECURE/CSRF_COOKIE_SECURE(Cookie를 HTTPS 한정으로)SECURE_CONTENT_TYPE_NOSNIFF등- **
manage.py check --deploy**를 실행해 이들 설정 누락을 기계적으로 찾아냅니다.
5. 인가 (P1 — 가장 빈번한 사고원)
자주 하는(위험한)
- 로그인 필수지만 소유자 스코프가 없음
- 쿼리셋이 전건이고 ID로의 좁힘이 없음
- 숨기기만 한 URL/추측하기 어려운 ID에 의존
- 일부 뷰에서 권한 체크를 통과시키는 것을 잊음
올바른
- 로그인 필수+권한 체크를 명시
- 취득도
filter(user=request.user)등으로 소유자에 한정 - 취득·갱신·삭제의 모든 경로에서 확인
- 인가는 명시적으로 구성하고, 기본값에 맡기지 않기
용어는 IDOR란. 인증과 인가는 별개이며, 인가는 데이터에 가까운 곳에서 확인합니다.
6. 인젝션과 출력 (P2)
- SQL: ORM은 바인드합니다.
raw()/extra()나 문자열 결합으로 쿼리를 만들지 않습니다(→ SQL 인젝션이란). - XSS: 템플릿은 기본값으로 자동 이스케이프됩니다.
mark_safe/|safe에 사용자 입력을 넘기지 않습니다(→ XSS란). - 역직렬화: 신뢰할 수 없는
pickle을 읽지 않습니다(코드 실행으로 이어질 수 있음).
7. CSRF·세션·admin (P2)
- CSRF 보호(기본값)를 비활성화하지 않습니다(→ CSRF란).
- admin의 노출을 좁힙니다(접근 제한·URL 변경·다중 인증). 클릭재킹 대책(
X-Frame-Options기본값)을 살립니다. - 세션에도 secure/httponly/samesite를 적용하고 로그인 시 재생성합니다.
8. SSRF·업로드·헤더 (P2)
- 서버가 사용자 지정 URL을 취득하는 처리는 허용 리스트로 대상을 한정하고, 내부 IP/메타데이터로의 도달을 차단합니다(→ SSRF란).
- 업로드는 종류·크기를 검증하고, 공개면 밖에 저장합니다.
- 본 사이트의 헤더는 보안 헤더 진단으로 확인할 수 있습니다.
검증: 내 Django는 정말 굳혀졌는가
만들면 끝이 아니라, 점검해야 비로소 완료입니다. 다음은 자신의 환경에 대한 방어적 자기 점검입니다.
설정 누락을 기계 점검
python manage.py check --deploy를 실행해 경고가 해소되었는지 확인.프로덕션에서 DEBUG가 노출되지 않는가
인가가 작동하는가
시크릿과 의존성
SECRET_KEY가 리포지토리에 없는지, pip-audit/osv가 클린인지 확인.본 사이트의 관점: 배터리 포함이라도 '설정과 인가'는 자신의 책임
Django는 많은 것을 기본값으로 지키지만, 프로덕션의 설정(DEBUG/SECRET_KEY/ALLOWED_HOSTS/SSL)과 인가만은, 환경별·앱별로 자신이 올바르게 결정해야 합니다. 본 사이트가 반복해서 보는 사고도, 정교한 공격보다 "프로덕션에서 디버그가 열려 있었다" "시크릿이 노출되어 있었다" "인가가 없었다"라는 설정·운영의 유형이 중심입니다. 그래서 방어의 무게 중심은 프로덕션 설정을 죄고, 시크릿을 비공개로 유지하며, 인가를 명시하는 것. check --deploy를 운영에 포함시키는 것이 지름길입니다.
다음으로 읽기
- 입구: 프레임워크별 보안(입구) · Laravel 보안(프로덕션 DEBUG·시크릿 노출이 가깝다)
- 실무: 취약점 대응 실무 · 의존성 CVE 모니터링 · 공개 디렉터리에 시크릿을 두지 않기
- 용어: IDOR란 · SQL 인젝션 · XSS · CSRF · SSRF
- 도구: 보안 헤더 진단
FAQ
QDjango 보안, 무엇부터 해야 하나요?
우선순위 P0의 3가지입니다. (1) 프로덕션에서 DEBUG=False를 확실히 하고 ALLOWED_HOSTS를 올바르게 설정하기, (2) SECRET_KEY를 코드/리포지토리에 쓰지 말고 환경에서 읽어 들이며 누출 시 로테이션하기, (3) pip 의존성의 CVE를 기계 모니터링하고 실가동 버전으로 판정해 즉시 패치. 다음으로 프로덕션 보안 설정(SSL/HSTS/Cookie)과 인가로 넘어갑니다. manage.py check --deploy로 설정 누락을 기계적으로 점검할 수 있습니다.
Q프로덕션에서 DEBUG=True로 두면 무엇이 위험한가요?
DEBUG가 활성화되면 오류 화면에 설정값·환경 변수·스택 트레이스 등 내부 정보가 상세히 표시될 수 있습니다. 공격자는 일부러 오류를 일으켜 정보를 뽑아낼 수 있습니다. 프로덕션에서는 반드시 DEBUG=False로 하고 ALLOWED_HOSTS를 올바르게 설정하세요. 아울러 상세 오류의 외부 노출을 막고, 정적/미디어 배포도 프로덕션에 맞게 재검토합니다.
QSECRET_KEY는 왜 중요한가요?
SECRET_KEY는 서명된 Cookie와 세션, CSRF 토큰, 비밀번호 재설정 등의 토대가 되는 키입니다. 누출되면 이들의 위조나 변조로 이어질 수 있습니다. 코드나 리포지토리에 쓰지 말고, 환경 변수나 시크릿 매니저에서 읽어 들이며, 만일 누출되면 신속히 로테이션하세요. 공개 디렉터리나 DEBUG 화면에서 노출되지 않게 하는 것도 중요합니다.
QDjango의 프로덕션 보안 설정에서 봐야 할 항목은?
SecurityMiddleware 관련이 중심입니다. SECURE_SSL_REDIRECT(HTTPS 강제), SECURE_HSTS_SECONDS(HSTS), SESSION_COOKIE_SECURE / CSRF_COOKIE_SECURE(Cookie를 secure로), SECURE_CONTENT_TYPE_NOSNIFF 등을 프로덕션에 맞게 설정합니다. manage.py check --deploy를 실행하면 이들 설정 누락을 기계적으로 찾아낼 수 있습니다.
Q의존성 패키지(pip)의 취약점은 어떻게 관리하나요?
pip-audit나 osv-scanner로 알려진 CVE를 기계 모니터링하고, '실가동 버전'으로 판정해 신속히 패치합니다. Django 본체와 Python을 지원 대상 버전으로 유지하고, EOL 버전을 방치하지 마세요. 의존성의 신선도는 정교한 공격보다 사고를 가르는 현실적인 요인입니다.