Efek mengubah SECRET_KEY Django


202

Saya membuat kesalahan dan memasukkan proyek Django saya SECRET_KEYke repositori publik.

Kunci ini seharusnya dirahasiakan menurut dokumen https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-SECRET_KEY

Proyek Django aktif dan telah berjalan untuk sementara waktu dengan beberapa pengguna aktif. Apa efeknya jika saya mengubah SECRET_KEY? Apakah ada pengguna, cookie, sesi, dll. Yang terpengaruh? Jelas, yang baru SECRET_KEYtidak akan lagi disimpan di lokasi publik.

Jawaban:


199

Sunting: Jawaban ini didasarkan pada Django 1.5

SECRET_KEY digunakan di banyak tempat yang berbeda, saya akan menunjukkan apa yang terkena dampaknya terlebih dahulu dan kemudian mencoba untuk membahas daftar itu dan memberikan penjelasan yang tepat tentang dampaknya.

Daftar hal-hal menggunakan SECRET_KEYsecara langsung atau tidak langsung:

Pada kenyataannya banyak item yang tercantum di sini digunakan SECRET_KEYmelalui django.utils.crypt.get_random_string()yang menggunakannya untuk seed mesin acak. Ini tidak akan terpengaruh oleh perubahan nilai SECRET_KEY.

Pengalaman pengguna yang secara langsung dipengaruhi oleh perubahan nilai adalah:

  • sesi, decode data akan pecah, yang berlaku untuk setiap sesi backend (cookie, basis data, berbasis file atau cache).
  • token atur ulang kata sandi yang sudah dikirim tidak akan berfungsi, pengguna harus bertanya yang baru.
  • formulir komentar (jika menggunakan django.contrib.comments) tidak akan memvalidasi jika diminta sebelum nilai berubah dan dikirimkan setelah perubahan nilai. Saya pikir ini sangat kecil tetapi mungkin membingungkan bagi pengguna.
  • pesan (dari django.contrib.messages) tidak akan memvalidasi sisi server dalam kondisi waktu yang sama seperti untuk formulir komentar.

UPDATE : sekarang bekerja pada Django 1.9.5, melihat sekilas pada sumbernya memberi saya jawaban yang hampir sama. Bisa lakukan pemeriksaan menyeluruh nanti.


1
Saya mengubah SECRET_KEY di server dev lokal saya dan itu tidak mengeluarkan saya, jadi sepertinya setidaknya sesi (cache) berfungsi dengan benar setelah perubahan. Bisakah Anda menjelaskan lebih lanjut tentang apa yang Anda maksud dengan data decode will breakdan mungkin menunjukkan beberapa kode (dalam Django atau proyek contoh) yang akan rusak? EDIT: masih menggunakan Django 1.4 - apakah begitu?
Kirill Zaitsev

@teferi Saya tidak tahu tentang 1.4, ini masalah melihat kode. Saya menunjuk pada semua sumber untuk setiap titik, Anda dapat melihat "melindungi data sesi dan membuat kunci sesi acak". Itu normal Anda masih login tetapi Anda tidak akan dapat membaca data yang terkandung dalam sesi seperti SECRET_KEYyang digunakan dalam salted_hmachash data sesi.
sberder

jika digunakan untuk kata sandi garam, bukankah itu berarti kata sandi dalam database harus diatur ulang?
Henning

7
@Henning, kurasa tidak. Kata sandi disimpan seperti <algorithm>$<iterations>$<salt>$<hash>dalam auth_user, sehingga garam acak disimpan di samping kata sandi dalam setiap kasus.
Denis Drescher

2
Apakah jawabannya berbeda secara signifikan untuk versi Django> 1.5? (misalnya 1.9 sekarang-sekarang)
das-g

36

Sejak pertanyaan ini diajukan, dokumentasi Django telah berubah untuk memasukkan jawaban.

Kunci rahasia digunakan untuk:

  • Semua sesi jika Anda menggunakan backend sesi lain selain django.contrib.sessions.backends.cache, atau menggunakan default get_session_auth_hash().
  • Semua pesan jika Anda menggunakan CookieStorageatau FallbackStorage.
  • Semua PasswordResetViewtoken.
  • Setiap penggunaan penandatanganan kriptografis, kecuali kunci yang berbeda disediakan.

Jika Anda memutar kunci rahasia Anda, semua hal di atas akan batal. Kunci rahasia tidak digunakan untuk kata sandi pengguna dan rotasi kunci tidak akan memengaruhi mereka.

Tidak jelas bagi saya bagaimana saya harus memutar kunci rahasia. Saya menemukan diskusi tentang bagaimana Django menghasilkan kunci untuk proyek baru , serta Gist yang membahas opsi lain . Saya akhirnya memutuskan untuk membuat Django membuat proyek baru, menyalin kunci rahasia baru ke proyek lama saya, dan kemudian menghapus proyek baru .

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

Memperbarui

Sepertinya Django menambahkan get_random_secret_key()fungsi di versi 1.10. Anda bisa menggunakannya untuk menghasilkan kunci rahasia baru.

$ ./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
Apakah pembuatan kunci rahasia bergantung pada kunci rahasia?
kdazzle

4
Tidak, @kdazzle, jika Anda melihat kode sumbernyastartproject , Anda dapat melihat bahwa itu hanya menghasilkan string acak menggunakan cryptomodul.
Don Kirkby

12
Heh, maaf, @DonKirkby, lelucon buruk
kdazzle

16

Menurut halaman ini https://docs.djangoproject.com/en/dev/topics/signing/ , SECRET_KEY sebagian besar digunakan untuk hal-hal sementara - menandatangani data yang dikirim melalui kabel sehingga Anda dapat mendeteksi gangguan, misalnya. Sepertinya hal-hal yang BISA pecah adalah:

  • Cookie yang ditandatangani, mis. Nilai "ingat auth saya di komputer ini". Dalam hal ini, cookie akan tidak valid, tanda tangan akan gagal memverifikasi dan pengguna harus mengautentikasi ulang.
  • Untuk setiap pengguna yang telah meminta tautan untuk mengatur ulang kata sandi atau unduhan file khusus, tautan itu tidak lagi valid. Pengguna hanya perlu meminta kembali tautan tersebut.

Seseorang dengan pengalaman Django yang lebih baru dan / atau menonjol dari saya mungkin berpadu sebaliknya, tetapi saya curiga bahwa kecuali Anda secara eksplisit melakukan sesuatu dengan API penandatanganan, ini seharusnya hanya menciptakan ketidaknyamanan ringan bagi pengguna Anda.


6
Lalu mengapa tidak menghasilkan kunci baru di setiap server restart?
Osa

4
Mungkin akan menimbulkan masalah jika Anda menjalankan server yang sama menggunakan beberapa proses.
dbn

1
@ ya maukah Anda keluar SEMUA pengguna Anda setiap kali Anda mendorong kode / restart server Anda?
EralpB

6

String SECRET_KEY terutama digunakan untuk mengenkripsi dan / atau mem-hashing data cookie. Banyak kerangka kerja (termasuk Django) sampai di sini karena cookie sesi default memiliki kekurangannya sendiri.

Bayangkan Anda memiliki formulir dalam Django untuk mengedit artikel dengan bidang tersembunyi. Dalam bidang tersembunyi ini tersimpan ID artikel yang telah Anda edit. Dan jika Anda ingin memastikan bahwa tidak ada yang dapat mengirimi Anda id artikel lain, Anda akan menambahkan bidang tersembunyi tambahan dengan id hash. Jadi jika seseorang akan mengubah ID, Anda akan mengetahuinya karena hash tidak akan sama.

Tentu saja ini adalah contoh sepele tetapi ini adalah bagaimana SECRET_KEY digunakan.

Django secara internal menggunakannya misalnya untuk {% csrf_token%} dan beberapa hal lainnya. Ini benar-benar tidak akan berdampak pada aplikasi Anda jika Anda akan mengubahnya, berdasarkan pertanyaan Anda dan bahwa Anda tidak menggunakannya.

Satu-satunya hal adalah mungkin nilai sesi akan turun. Jadi misalnya pengguna harus masuk ke admin lagi, karena Django tidak akan dapat memecahkan kode sesi dengan kunci yang berbeda.


1

Saya membuat kesalahan yang sama. Kata sandi default adalah 50 panjang jadi saya menggunakan PowerShell untuk menghasilkan 50 string acak panjang dan mengganti SECRET_KEY lama dengan itu. Saya masuk dan setelah mengganti SECRET_KEY, sesi saya sebelumnya tidak valid.

Dengan Powershell ( sumber ):

# 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)

Dengan Bash ( sumber ):

# 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

Pada titik ini saya berpikir mengapa tidak mencoba kunci yang lebih besar, jadi saya mencobanya dengan kunci panjang 100 dan 1000. Keduanya bekerja. Jika saya mengerti kode sumber , objek yang dikembalikan oleh fungsi penanda adalah hash hmac di base64. RFC 2104 mengatakan ini untuk panjang kunci kunci HMAC yang diperlukan.

Aplikasi yang menggunakan kunci lebih lama dari B byte pertama akan hash kunci menggunakan H dan kemudian menggunakan string L byte yang dihasilkan sebagai kunci aktual untuk HMAC.

Kunci untuk HMAC dapat berupa panjang apa saja (kunci lebih panjang dari B byte di hash pertama kali menggunakan H). Namun, kurang dari L byte sangat tidak disarankan karena akan mengurangi kekuatan keamanan fungsi. Kunci yang lebih panjang dari L byte dapat diterima tetapi panjang ekstra tidak akan secara signifikan meningkatkan kekuatan fungsi. (Kunci yang lebih panjang mungkin disarankan jika keacakan kunci dianggap lemah.)

Untuk menerjemahkan ke bicara normal, ukuran kunci rahasia harus sama dengan ukuran output. Kuncinya juga harus dalam bit. Setiap digit di base64 mewakili 6 bit. Jadi jika Anda memiliki kata sandi 50 karakter, Anda akan memiliki kunci rahasia 50 x 6 = 300 bit. Jika Anda menggunakan SHA256, maka Anda memerlukan kunci 256 bit ( sha256 menggunakan 256 bit menurut definisi ). Jadi kata sandi 50 panjang harus bekerja kecuali Anda berencana untuk menggunakan algoritma hashing lebih besar dari SHA256.

Tetapi karena ada bit tambahan dalam kunci yang hash, ukuran itu tidak akan secara drastis menurunkan kinerja. Tapi itu akan menjamin Anda bahwa Anda memiliki bit yang cukup untuk fungsi hash yang lebih besar. SHA-512 akan dilindungi oleh SECRET_KEY 100 panjang ( 50 x 6 = 600 bit> 512 bit ).

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.