はじめに
個人でpythonとDjangoでサイトを作成しました。
技術者として次のステップアップするためセキュリティに目を向けてみましょう。
Django標準の機能でセキュリティチェックをしてみましょう。
結論
Djangoが標準で用意してくれているcheckコマンドを使いましょう。
なにをチェックしてくれるのか
Djangoの設定が正しいかどうかをみれくれます。
具体的にはデバックモードがOFFになっているか、セキュアなCookie設定かなどを確認する必要があります。
使うコマンドは?
manage.pyのcheckコマンドです。
--deployオプションを付けて実行することで、本番環境で稼働させることを想定した厳格なチェックをしてくれます。
このコマンドは、settings.pyファイルなどを確認します。
以下のことを自動で検証してくれます。
-
DEBUGの設定: 本番環境で DEBUG = Trueになっていると、エラー発生時にアプリケーションの内部情報が外部に漏れてしまう危険があります。Falseになっているかを確認します -
SECRET_KEYの管理: SECRET_KEY が推測しやすいものでないか、また、バージョン管理(Gitなど)に直接ハードコードされていないかなどを確認します -
ALLOWED_HOSTSの設定: アプリケーションがどのドメインからのリクエストを受け付けるかを定義します。本番環境でこれが空だったり、ワイルドカード(*)になっていたりす
ると、セキュリティリスクとなります -
HTTPS関連の設定:
- SECURE_SSL_REDIRECT: HTTPリクエストを自動的にHTTPSにリダイレクトするか
- SESSION_COOKIE_SECURE: セッションCookieをHTTPS接続でのみ送信するか
- CSRF_COOKIE_SECURE: CSRFトークンCookieをHTTPS接続でのみ送信するか
これらの設定が一つでも漏れていると、中間者攻撃などに対して脆弱になる可能性があります
実行してみた
私のアプリはDockerコンテナ上で動いています。
- まずはDockerコンテナを起動します
docker-compose up -d
- コンテナ内で実行します
docker-compose exec web python manage.py check --deploy
- docker-compose exec web: webコンテナの中で次のコマンドを実行するという意味です
- python manage.py check --deploy: Djangoのチェックコマンド本体です
- 実行結果はこんな感じ
(venv) ****-****:~/kidsPlayGround$ docker-compose exec web python3 manage.py check --deploy
System check identified some issues:
WARNINGS:
?: (security.W004) You have not set a value for the SECURE_HSTS_SECONDS setting. If your entire site is served only over SSL, you may want to consider setting a value and enabling HTTP Strict Transport Security. Be sure to read the documentation first; enabling HSTS carelessly can cause serious, irreversible problems.
?: (security.W008) Your SECURE_SSL_REDIRECT setting is not set to True. Unless your site should be available over both SSL and non-SSL connections, you may want to either set this setting True or configure a load balancer or reverse-proxy server to redirect all connections to HTTPS.
?: (security.W009) Your SECRET_KEY has less than 50 characters, less than 5 unique characters, or it's prefixed with 'django-insecure-' indicating that it was generated automatically by Django. Please generate a long and random value, otherwise many of Django's security-critical features will be vulnerable to attack.
?: (security.W012) SESSION_COOKIE_SECURE is not set to True. Using a secure-only session cookie makes it more difficult for network traffic sniffers to hijack user sessions.
?: (security.W016) You have 'django.middleware.csrf.CsrfViewMiddleware' in your MIDDLEWARE, but you have not set CSRF_COOKIE_SECURE to True. Using a secure-only CSRF cookie makes it more difficult for network traffic sniffers to steal the CSRF token.
?: (security.W018) You should not have DEBUG set to True in deployment.
System check identified 6 issues (0 silenced).
なんかいろいろ出てきましたね
警告内容の意味はこんな感じ
- DEBUG が True になっている (W018)
- 問題: DEBUG = True は、エラー発生時にデバッグ情報(設定内容など)をブラウザに表示してしまい、攻撃者に重要な情報を与えるため、本番環境ではFalseにすべきです
- 深刻度: 非常に高い
- SECRET_KEY が脆弱である (W009)
- 問題: 現在の SECRET_KEY は、Djangoが自動生成した仮のものか、非常に単純な文字列です。このキーはパスワードリセットなど多くのセキュリティ機能の根幹をなすため、長くランダムな文字列でないと、アプリケーションの安全性が著しく低下します
- 深刻度: 非常に高い
- HTTPS関連の設定が不足している (W008, W012, W016)
これらの警告は、サイトを常時HTTPS(SSL)で運用するための設定が不足していることを示しています。
-
SECURE_SSL_REDIRECT(W008): True にしないと、HTTPでのアクセスを許可してしまいます。HTTPSに自動でリダイレクトさせるべきです -
SESSION_COOKIE_SECURE(W012): Trueにしないと、暗号化されていないHTTP通信でセッションIDが送信される可能性ありです。セッションハイジャック(なりすまし)のリスクが高まります -
CSRF_COOKIE_SECURE(W016): 上記と同様に、CSRFトークンがHTTPで送信される可能性があり、セキュリティリスクとなります -
深刻度: 高い
- HSTS設定がされていない (W004)
-
SECURE_HSTS_SECONDS:これは、一度サイトにHTTPSでアクセスしたブラウザに対し、「今後は指定した期間、絶対にHTTPSでしかアクセスしてはいけない」と強制する強力な仕組み(HTTP StrictTransport Security)です。設定は推奨されますが、導入は慎重に行う必要があります - 深刻度: 中(上記1〜3を優先して対応すべき)
セキュリティ対応してみた
初期対応
自分ではハードル大変なので、ここからはGeminiCliと勧めていきます。
設定ファイルの書き方って調べないとかけないから、こんなときAIって便利だよね。
.envファイルのシークレットキーも更新しろと警告でているので変更していきます。
以下のコマンドを実行すると、Djangoの機能を使って安全なキーが作成できます。
python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'
対応2回目
修正が終わったのでもう一度コマンドを実行して確認してみましょう。
(venv) ***$ docker-compose exec -e DJANGO_SETTINGS_MODULE=mysite.settings.prod web python manage.py check --deploy
System check identified some issues:
WARNINGS:
?: (security.W005) You have not set the SECURE_HSTS_INCLUDE_SUBDOMAINS setting to True. Without this, your site is potentially vulnerable to attack via an insecure connection to a subdomain. Only set this to True if you are certain that all subdomains of your domain should be served exclusively via SSL.
?: (security.W009) Your SECRET_KEY has less than 50 characters, less than 5 unique characters, or it's prefixed with 'django-insecure-' indicating that it was generated automatically by Django. Please generate a long and random value, otherwise many of Django's security-critical features will be vulnerable to attack.
?: (security.W021) You have not set the SECURE_HSTS_PRELOAD setting to True. Without this, your site cannot be submitted to the browser preload list.
いままでのはだいたい大丈夫そう。
今回新たに出てきた2つの警告 (W005, W021) は、前回追加した SECURE_HSTS_SECONDS に関連する、より高度なHSTS(HTTP Strict Transport Security)の設定です。
-
SECURE_HSTS_INCLUDE_SUBDOMAINS(W005): HSTSをサブドメイン(例: sub.example.com)にも適用するかどうかの設定です -
SECURE_HSTS_PRELOAD(W021): あなたのサイトをブラウザの「プリロードリスト」に申請するための設定です。リストに登録されると、ユーザーが初回アクセス時から強制的にHTTPSで接続するようになり、最も安全性が高まります
SECRET_KEYに関するのは、DockerをRestartして.envを読み込み直したら大丈夫かな?
docker compose restart web
対応完了!
コマンドを実行してセキュリティチェックしてみましょう
本番用の設定ファイルを見るためにコマンドで設定ファイルを指定しています。
(venv) jam@jam-RL5C-R35T:~/kids-webapp/kidsPlayGround$ docker-compose exec -e DJANGO_SETTINGS_MODULE=mysite.settings.prod web python manage.py check --deploy
System check identified no issues (0 silenced).
よっしゃ!おわりました!
まとめ
Djangoの標準コマンドでセキュリティチェックができました。
シンプルでかんたんにチェックできるのは素晴らしいですね。
また、コマンド操作なのでAIとの相性も◎でした。
以下が標準の書き方です。設定ファイルの状況やコンテナを使っているかどうかで書き方も変わるのでAIに聞いてください。
manage.py check --deploy
では、よきプログラマーライフを!
