DjangoのSECRET_KEYの変更による影響


202

私は間違いを犯し、DjangoプロジェクトをSECRET_KEYパブリックリポジトリにコミットしました。

このキーはドキュメントhttps://docs.djangoproject.com/en/dev/ref/settings/#std:setting-SECRET_KEYに従って秘密にしておくべきでした

Djangoプロジェクトはライブで、しばらくの間アクティブなユーザーが何人かいます。変更するとSECRET_KEYどうなりますか?既存のユーザー、Cookie、セッションなどに影響はありますか?明らかに、新しいものSECRET_KEYは公共の場所に保存されなくなります。

回答:


199

編集:この回答はdjango 1.5に基づいています

SECRET_KEY はさまざまな場所で使用されています。最初に、その影響を受けるものを指摘し、次にそのリストを調べて、影響について正確に説明します。

SECRET_KEY直接的または間接的に使用するもののリスト:

実際に使用してここに記載されている項目の多くSECRET_KEYを通じてdjango.utils.crypt.get_random_string()、それを使用するには、ランダムなエンジンをシードします。これは、の値の変更による影響を受けませんSECRET_KEY

値の変更によって直接影響を受けるユーザーエクスペリエンスは次のとおりです。

  • セッション、データデコードは中断します。これは、どのセッションバックエンド(Cookie、データベース、ファイルベース、またはキャッシュ)でも有効です。
  • すでに送信されたパスワードリセットトークンは機能しません。ユーザーは新しいトークンを要求する必要があります。
  • コメントフォーム(を使用している場合django.contrib.comments)は、値の変更前に要求され、値の変更後に送信されたかどうかを検証しません。これは非常にマイナーですが、ユーザーを混乱させるかもしれません。
  • (からのdjango.contrib.messages)メッセージは、コメントフォームの場合と同じタイミング条件でサーバー側を検証しません。

更新:django 1.9.5に取り組んでいます。ソースをざっと見ると、ほぼ同じ答えが得られます。後で完全な検査を行う場合があります。


1
私はローカルの開発サーバーでSECRET_KEYを変更していますが、ログアウトしません。そのため、変更後、少なくともセッション(キャッシュ)は正しく機能しているようです。あなたが何を意味するかについてさらに詳しく説明してください、data decode will breakそしておそらく壊れるいくつかのコード(djangoまたはサンプルプロジェクト内)を指摘できますか?編集:まだdjango 1.4を使用しています-そうですか?
Kirill Zaitsev

@teferi 1.4についてはわかりません。コードを確認するだけです。各ポイントのすべてのソースを指摘しましたが、「セッションデータを保護してランダムセッションキーを作成する」をご覧ください。通常はログインしたままですが、セッションデータのハッシュSECRET_KEYsalted_hmac使用されているように、セッションに含まれているデータを読み取ることはできません。
sberder 2013

パスワードハッシュソルトに使用する場合、データベースのパスワードをリセットする必要があるという意味ではありませんか?
ヘニング

7
@ヘニング私はそうは思いません。パスワードが保存されているよう<algorithm>$<iterations>$<salt>$<hash>にランダム塩はそれぞれの場合のパスワードと一緒に保存されているので、AUTH_USERインチ
Denis Drescher 2014年

2
Djangoバージョン> 1.5では、答えは大きく異なりますか?(例:現在の1.9)
das-g

36

この質問が行われたため、Djangoのドキュメントは回答を含むように変更されました。

秘密鍵は次の目的で使用されます。

  • 以外のセッションバックエンドdjango.contrib.sessions.backends.cacheを使用している場合、またはデフォルトを使用している場合は、すべてのセッションget_session_auth_hash()
  • CookieStorageまたはを使用している場合のすべてのメッセージFallbackStorage
  • すべてのPasswordResetViewトークン。
  • 別のキーが提供されない限り、暗号化署名の使用。

秘密鍵をローテーションすると、上記のすべてが無効になります。秘密鍵はユーザーのパスワードには使用されず、鍵のローテーションはそれらに影響を与えません。

秘密鍵をどのようにローテーションするべきか正確には分かりませんでした。Djangoが新しいプロジェクトのキーを生成する方法についての議論と、他のオプションについて議論するGist を見つけました。Djangoで新しいプロジェクトを作成し、新しい秘密鍵を古いプロジェクトにコピーして、新しいプロジェクトを消去することにしました

cd ~/junk # Go to some safe directory to create a new project.
django-admin startproject django_scratch
grep SECRET_KEY django_scratch/django_scratch/settings.py # copy to old project
rm -R django_scratch

更新

Django がバージョン1.10でget_random_secret_key()関数を追加したようです。これを使用して、新しい秘密鍵を生成できます。

$ ./manage.py shell -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
s!)5@5s79sp=92a+!f4v!1g0d0+64ln3d$xm1f_7=749ht&-zi
$ ./manage.py shell -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
_)+%kymd=f^8o_fea1*yro7atz3w+5(t2/lm2cz70*e$2mn\g3
$

4
秘密鍵の生成は秘密鍵に依存していますか?
kdazzle 2015年

4
いいえ、@ kdazzle、のソースコードをstartproject見ると、cryptoモジュールを使用してランダムな文字列を生成するだけであることがわかります。
Don Kirkby、2015年

12
へえ、申し訳ありません、@ DonKirkby、冗談
kdazzle 2015年

16

このページhttps://docs.djangoproject.com/en/dev/topics/signing/によると、SECRET_KEYは主に一時的なものに使用されます。たとえば、改ざんを検出できるようにネットワーク経由で送信されるデータに署名します。壊れることができるもののようです:

  • 署名付きCookie、たとえば「このコンピューターで私の認証を記憶する」タイプの値。この場合、Cookieは無効になり、署名は検証されず、ユーザーは再認証する必要があります。
  • パスワードのリセットまたはカスタムファイルのダウンロードのリンクを要求したユーザーの場合、それらのリンクは無効になります。ユーザーは単にそれらのリンクを再要求する必要があります。

私よりもDjangoの経験が最近の人や目立った人は、そうでないと不満を感じるかもしれませんが、署名APIを使用して明示的に何かを行わない限り、ユーザーにわずかな不便が生じるだけだと思います。


6
次に、サーバーを再起動するたびに新しいキーを生成しませんか?
osa 14

4
複数のプロセスを使用して同じサーバーを実行している場合は、おそらく問題が発生します。
dbn 2014年

1
@osaは、コードをプッシュ/サーバーを再起動するたびにすべてのユーザーをログアウトしますか?
EralpB

6

SECRET_KEY文字列は、主にCookieデータの暗号化やハッシュに使用されます。デフォルトのセッションCookieには独自の欠点があるため、多くのフレームワーク(Djangoを含む)がこれに該当します。

djangoに、非表示フィールドのある記事を編集するためのフォームがあるとします。この非表示フィールドには、編集している記事のIDが格納されます。また、誰もあなたに他の記事IDを送信できないようにしたい場合は、ハッシュされたIDを持つ非表示フィールドを追加します。そのため、誰かがIDを変更する場合、ハッシュは同じではないため、IDを知っています。

もちろん、これは簡単な例ですが、SECRET_KEYの使用方法はこれです。

Djangoは内部的に、たとえば{%csrf_token%}やその他いくつかのためにそれを使用しています。質問に基づいてそれを変更し、使用していない場合でも、アプリケーションに影響を与えることはありません。

唯一のことは、おそらくセッションの値が削除されることです。したがって、たとえば、djangoは異なるキーでセッションをデコードできないため、ユーザーは再度adminにログインする必要があります。


1

私も同じ間違いをしました。デフォルトのパスワードは50長いため、Powershellを使用して50の長いランダム文字列を生成し、古いSECRET_KEYをそれに置き換えました。私はログインしていて、SECRET_KEYを置き換えた後、以前のセッションが無効になりました。

Powershell(ソース):

# Load the .net System.Web namespace which has the GeneratePassword function
[Reflection.Assembly]::LoadWithPartialName("System.Web")

#  GeneratePassword(int length, int numberOfNonAlphanumericCharacters)
[System.Web.Security.Membership]::GeneratePassword(50,5)

Bashの場合(ソース):

# tr includes ABCabc123 and the characters from OWASP's "Password special characters list"
cat /dev/urandom | tr -dc 'A-Za-z0-9!"#$%&\''()*+,-./:;<=>?@[\]^_`{|}~' | head -c 100 ; echo

この時点で、もっと大きなキーを試してみませんかと思ったので、100と1000の長いキーで試してみました。どちらもうまくいきました。ソースコードを理解していれば、signer関数によって返されるオブジェクトはbase64のhmacハッシュです。RFC 2104は、HMAC秘密鍵の必要な長さについてこれを言っています。

Bバイトより長いキーを使用するアプリケーションは、最初にHを使用してキーをハッシュし、次に結果のLバイト文字列をHMACへの実際のキーとして使用します。

HMACのキーの長さは任意です(Bバイトより長いキーは、最初にHを使用してハッシュされます)。ただし、関数のセキュリティ強度が低下するため、Lバイト未満にしないことを強くお勧めします。Lバイトより長いキーは受け入れられますが、追加の長さは機能の強度を大幅に増加させません。(キーのランダム性が弱いと考えられる場合は、キーを長くすることをお勧めします。)

通常の発言に変換するには、秘密鍵のサイズが出力と同じサイズである必要があります。キーもビットである必要があります。base64の各桁は6ビットを表します。したがって、50文字のパスワードを持っている場合は、50 x 6 = 300ビットの秘密鍵になります。SHA256を使用している場合は、256ビットの鍵が必要になります(sha256は定義により256ビットを使用します)。したがって、SHA256より大きいハッシュアルゴリズムを使用する予定がない限り、50の長いパスワードが機能するはずです。

ただし、キーの余分なビットはハッシュされるため、そのサイズによってパフォーマンスが大幅に低下することはありません。しかし、それはあなたがより大きなハッシュ関数のために十分なビットを持っていることを保証するでしょう。SHA-512は、100の長いSECRET_KEY(50 x 6 = 600ビット> 512ビット)でカバーされます

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.