Djangoの本番設定をすべて「セキュリティを強くする設定」と覚えると、保護範囲が曖昧になります。Django 5.2 LTSを前提に、攻撃やリスクと対応付けて整理します。
HTTPSへ転送する設定とCookieを守る設定は別
本番設定では、次の3つが並ぶことがあります。
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_SSL_REDIRECTはHTTPリクエストをHTTPSのURLへ転送し、SecurityMiddlewareが処理します。残りの2つはCookieにSecure属性を付けます。
| 設定 | 保護する対象 | ブラウザの動作 |
|---|---|---|
SESSION_COOKIE_SECURE |
ログイン状態などを識別するセッションCookie | HTTPS接続だけで送信する |
CSRF_COOKIE_SECURE |
CSRF検証に使うCookie | HTTPS接続だけで送信する |
リダイレクトだけではCookieを守れません。公衆Wi-Fi上で最初にhttp://example.comへアクセスすると、転送前にHTTPリクエストが発生します。Secure属性がなければ既存Cookieが付く可能性があります。
このためHTTPSへの転送と、HTTPではCookieを送らせない設定の両方が必要です。ただしSecure属性自体が通信を暗号化するわけではありません。
リバースプロキシ配下ではHTTPSの判定に注意する
TLSをロードバランサーで終端すると、その先のDjangoまではHTTPになることがあります。Djangoが元の通信を誤認すると、リダイレクトループが起きる可能性があります。
プロキシが信頼できるヘッダーを適切に設定する構成では、例えば次を使います。
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
これは無条件に使えません。プロキシが外部由来の同名ヘッダーを除去し、HTTPSだった通信にだけ安全に付与することを確認します。条件を満たさないとHTTPS判定を偽装されるおそれがあります。
MIME sniffingを抑止するnosniff
SECURE_CONTENT_TYPE_NOSNIFF = True
この設定が有効でSecurityMiddlewareが組み込まれていると、Djangoは次のレスポンスヘッダーを付けます。
X-Content-Type-Options: nosniff
ブラウザが内容から種類を推測するMIME sniffingは、サーバーのContent-Typeと異なる解釈につながる場合があります。
例えばアップロードファイルを誤った種類で配信すると、実行可能な内容として扱われる余地が生まれます。nosniffはこの誤解釈を抑えます。
ただし、Content-Typeの誤設定やXSS全体を直す機能ではありません。正しい種類で安全に配信することが前提です。Django 5.2の既定値はTrueです。
iframeを悪用するクリックジャッキング
攻撃者が対象サイトを透明なiframeとして重ね、利用者には別のボタンがあるように見せます。その位置に「購入」などの操作が隠れていれば、意図しないクリックをさせられます。これがクリックジャッキングです。
X_FRAME_OPTIONS = "DENY"
XFrameOptionsMiddlewareがX-Frame-Options: DENYを返し、フレーム内表示を拒否させます。SAMEORIGINなら同一オリジンだけを許可します。
Django 5.2の既定値はDENYで、startprojectのsettingsには同ミドルウェアも含まれます。正当なiframeが必要なら、対象ビューだけの例外を検討します。
設定が機能する条件を確認する
| 設定 | Django 5.2の既定値 | 主な条件 |
|---|---|---|
SECURE_SSL_REDIRECT |
False |
SecurityMiddlewareと正しいHTTPS判定 |
SESSION_COOKIE_SECURE |
False |
サイトをHTTPSで提供すること |
CSRF_COOKIE_SECURE |
False |
サイトをHTTPSで提供すること |
SECURE_CONTENT_TYPE_NOSNIFF |
True |
SecurityMiddleware |
X_FRAME_OPTIONS |
"DENY" |
XFrameOptionsMiddleware |
HTTPの開発環境でSecure Cookieを有効にすると、ログインやCSRF検証が動かないことがあります。環境別に設定を分ける理由の1つです。
まとめ
- HTTPSリダイレクトとCookieの
Secure属性は役割が異なる - プロキシ配下では、Djangoが元の通信をHTTPSと安全に判定できる構成が必要
-
nosniffはContent-Typeの推測を抑えるが、誤設定やXSS全体を解決するものではない -
X_FRAME_OPTIONS="DENY"はiframe表示を拒否し、クリックジャッキングを抑止する - 設定値だけでなく、ミドルウェア、HTTPS、プロキシの条件まで確認する