Gunicorn: Pengaturan cipher SSL default menonaktifkan cipher yang paling aman

Dibuat pada 23 Jan 2019  ·  3Komentar  ·  Sumber: benoitc/gunicorn

Default untuk opsi --ciphers adalah TLSv1 .

Nilai ini merupakan default yang buruk, karena secara aktif menonaktifkan sandi baru yang kuat yang hanya tersedia dengan TLSv1.2. Secara khusus, tidak ada perpotongan antara kumpulan cipher yang dikonfigurasi oleh nilai default ini dan cipher yang diberi peringkat A+ oleh OWASP :

>>> import ssl
>>> ctx = ssl.SSLContext()
>>> ctx.set_ciphers('TLSv1')
>>> tlsv1 = {c['name'] for c in ctx.get_ciphers()}
>>> ctx.set_ciphers('DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256')  # From OWASP
>>> aplus = {c['name'] for c in ctx.get_ciphers()}
>>> aplus & tlsv1
set()

Ini dapat menyebabkan kesalahan OpenSSL NO_SHARED_CIPHER untuk klien yang dikonfigurasi dengan pengaturan keamanan tinggi.

Salah satu solusinya adalah dengan menambahkan cipher TLSv1.2 ke set, dengan mengubah default ke string 'TLSv1:TLSv1.2' . Ini akan menambah kompatibilitas untuk klien yang dikonfigurasi dengan pengaturan keamanan yang ketat, tanpa merusak pengguna gunicorn yang ada. Namun, ini akan meninggalkan cipher yang lemah di set.

Opsi yang lebih aman adalah memilih salah satu string OWASP sebagai default, berdasarkan tingkat kompatibilitas yang dijelaskan. Misalnya OWASP Cipher String C atau C- akan mempertahankan kompatibilitas yang luas sambil mengesampingkan cipher yang diketahui lemah.

Dalam kedua kasus tersebut, dokumentasi dapat diperbarui untuk merekomendasikan penggantian default dengan default yang lebih kuat berdasarkan penggunaan yang diharapkan, termasuk tautan ke halaman OWASP sebagai referensi.

Feedback Requested FeaturSSL

Komentar yang paling membantu

Juga, Python memiliki daftar sandi defaultnya sendiri: ia tidak pernah kembali ke default OpenSSL (yang tampaknya DEFAULT:!aNULL:!eNULL ). Ini dapat diakses sebagai ssl._DEFAULT_CIPHERS meskipun itu internal/tidak berdokumen, jadi cara untuk mengakses default adalah dengan tidak pernah memanggil set_ciphers() pada SSLContext.

Untuk Python 3.6 _DEFAULT_CIPHERS adalah

'TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:DH+CHACHA20:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:DH+HIGH:RSA+AESGCM:RSA+AES:RSA+HIGH:!aNULL:!eNULL:!MD5:!3DES'

Di Python 3.7 itu

'DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK'

dengan komentar yang mengatakan "DEFAULT: daftar sandi standar OpenSSL. Sejak 1.0.2 daftar dalam urutan yang masuk akal."

Pengaturan ini tampaknya cukup ketat, dan dalam semangat yang sama dengan OWASP.

Ada juga _RESTRICTED_SERVER_CIPHERS yang dimaksudkan untuk digunakan di server (sangat cocok untuk gunicorn) dan lebih ketat dari _DEFAULT_CIPHERS dalam beberapa versi Python, tetapi itu bersifat internal dan tidak digunakan di mana pun - tetapi telah dipertahankan setidaknya sejak 3.4.

Jadi opsi 3 adalah default untuk cipher suite default Python.

Satu-satunya alasan untuk tidak melakukannya adalah jika kami pikir kami dapat mengirimkan daftar hari ini yang lebih aman daripada versi Python yang lebih lama, atau bahwa kami ingin memilih salah satu level OWASP yang lebih ketat. Jujur itu cukup marjinal.

Semua 3 komentar

Terima kasih telah melaporkan permasalahan ini. Kami sangat menyadari hal ini. Gunicorn belum memiliki perubahan signifikan pada dukungan SSL-nya untuk sementara waktu. Lihat #1933 dan isu-isu yang terkait dalam diskusi itu.

Sementara itu, jika ada default yang lebih masuk akal sekarang karena Gunicorn hanya mendukung Python 3.4+, silakan ajukan permintaan tarik dan saya akan dengan senang hati menggabungkannya. Kami juga mempertimbangkan untuk mendorong versi minimum itu lebih tinggi, jadi jika ada versi Python minimum yang lebih tinggi yang akan mengaktifkan default yang lebih aman, harap posting informasi itu di sini untuk membantu mendorong keputusan itu sebelum rilis berikutnya.

Cipher yang tersedia (dan interpretasi argumen ke SSLContext.set_ciphers() ) tidak terpengaruh oleh versi Python, tetapi oleh versi OpenSSL/LibreSSL yang digunakan Python. Di Linux itu biasanya versi yang disediakan oleh distro.

Jika pertanyaan Anda adalah "dapatkah kami menetapkan default yang lebih aman yang selalu berfungsi di Python 3.4+" maka jawaban ketatnya adalah "tidak" karena itu tergantung bagaimana Anda mengkompilasi Python. Dimungkinkan untuk mengkompilasi Python baru-baru ini terhadap OpenSSL yang sangat lama yang tidak memiliki cipher yang kuat, jadi membutuhkan cipher yang kuat di gunicorn bisa berarti SSL tidak berfungsi sama sekali.

Namun, saya pikir kami cukup aman. Python 3.4 dirilis pada tahun 2014, sedangkan OpenSSL 1.0.1a, yang menambahkan TLSv1.2, dirilis pada bulan April 2012. Jadi versi distro Python mungkin akan memiliki cipher yang kuat. Hal lainnya adalah bahwa setiap rilis Python memerlukan versi OpenSSL tertentu (mis. Python 3.7 membutuhkan OpenSSL 1.0.2 Saya mengerti), tetapi saya tidak tahu persis apa versi Python memerlukan apa.

Secara keseluruhan saya harus dibimbing oleh OWASP. Mereka mengatakan C- adalah "Legacy, kompatibilitas terluas untuk browser lama dan perpustakaan lama" - dengan bonus tambahan yang dapat dikutip sebagai sumbernya.

Juga, Python memiliki daftar sandi defaultnya sendiri: ia tidak pernah kembali ke default OpenSSL (yang tampaknya DEFAULT:!aNULL:!eNULL ). Ini dapat diakses sebagai ssl._DEFAULT_CIPHERS meskipun itu internal/tidak berdokumen, jadi cara untuk mengakses default adalah dengan tidak pernah memanggil set_ciphers() pada SSLContext.

Untuk Python 3.6 _DEFAULT_CIPHERS adalah

'TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:DH+CHACHA20:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:DH+HIGH:RSA+AESGCM:RSA+AES:RSA+HIGH:!aNULL:!eNULL:!MD5:!3DES'

Di Python 3.7 itu

'DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK'

dengan komentar yang mengatakan "DEFAULT: daftar sandi standar OpenSSL. Sejak 1.0.2 daftar dalam urutan yang masuk akal."

Pengaturan ini tampaknya cukup ketat, dan dalam semangat yang sama dengan OWASP.

Ada juga _RESTRICTED_SERVER_CIPHERS yang dimaksudkan untuk digunakan di server (sangat cocok untuk gunicorn) dan lebih ketat dari _DEFAULT_CIPHERS dalam beberapa versi Python, tetapi itu bersifat internal dan tidak digunakan di mana pun - tetapi telah dipertahankan setidaknya sejak 3.4.

Jadi opsi 3 adalah default untuk cipher suite default Python.

Satu-satunya alasan untuk tidak melakukannya adalah jika kami pikir kami dapat mengirimkan daftar hari ini yang lebih aman daripada versi Python yang lebih lama, atau bahwa kami ingin memilih salah satu level OWASP yang lebih ketat. Jujur itu cukup marjinal.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat