الافتراضي لخيار --ciphers هو TLSv1
.
هذه القيمة هي قيمة افتراضية سيئة ، لأنها تعطل الأصفار الجديدة والقوية التي لا تتوفر إلا مع TLSv1.2. على وجه الخصوص ، لا يوجد تقاطع بين مجموعة الأصفار التي تم تكوينها بواسطة هذه القيمة الافتراضية والأصفار المصنفة A + بواسطة 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()
يمكن أن يؤدي هذا إلى أخطاء OpenSSL NO_SHARED_CIPHER
للعملاء الذين تم تكوينهم باستخدام إعدادات أمان عالية.
قد يكون أحد الحلول هو ببساطة إضافة TLSv1.2 ciphers إلى المجموعة ، عن طريق تغيير الافتراضي إلى السلسلة 'TLSv1:TLSv1.2'
. سيؤدي ذلك إلى إضافة التوافق للعملاء الذين تم تكوينهم باستخدام إعدادات أمان صارمة ، دون كسر أي مستخدمين حاليين لـ gunicorn. ومع ذلك ، فإن هذا من شأنه أن يترك الأصفار الضعيفة في المجموعة.
قد يكون الخيار الأكثر أمانًا هو اختيار أحد سلاسل OWASP كخيار افتراضي ، بناءً على مستوى التوافق الموصوف. على سبيل المثال ، تحافظ OWASP Cipher String C أو C- على توافق واسع مع استبعاد الأصفار الضعيفة المعروفة.
في كلتا الحالتين ، يمكن تحديث الوثائق للتوصية باستبدال الافتراضي بآخر افتراضي أقوى بناءً على الاستخدام المتوقع ، بما في ذلك ارتباط إلى صفحة OWASP كمرجع.
شكرا لك على الإبلاغ عن هذه المشكلة. نحن ندرك هذا جيدًا تمامًا. لم يجر Gunicorn تغييرات كبيرة على دعم SSL لفترة من الوقت. انظر # 1933 والقضايا المرتبطة بهذا النقاش.
في غضون ذلك ، إذا كان هناك افتراضي أكثر منطقية الآن حيث أن Gunicorn يدعم Python 3.4+ فقط ، فيرجى إرسال طلب سحب وسيسعدني دمجه. نحن نفكر أيضًا في دفع هذا الإصدار الأدنى إلى أعلى ، لذلك إذا كان هناك حد أدنى أعلى من إصدار Python الذي من شأنه تمكين تقصير أكثر أمانًا ، فيرجى نشر هذه المعلومات هنا للمساعدة في اتخاذ هذا القرار قبل الإصدار التالي.
لا تتأثر الأصفار المتاحة (وتفسير الوسيطة إلى SSLContext.set_ciphers()
) بإصدار Python ، ولكن بإصدار OpenSSL / LibreSSL الذي تبني عليه Python. في نظام Linux ، يكون هذا عادةً هو الإصدار الذي توفره التوزيعة.
إذا كان سؤالك هو "هل يمكننا تعيين إعداد افتراضي أكثر أمانًا يعمل دائمًا في Python 3.4+" ، فإن الإجابة الصارمة هي "لا" لأنها تعتمد على كيفية تجميع Python. قد يكون من الممكن تجميع Python حديثًا ضد OpenSSL القديم جدًا الذي يفتقر إلى الأصفار القوية ، لذا فإن طلب شفرات قوية في gunicorn قد يعني أن SSL لا يعمل على الإطلاق.
ومع ذلك ، أعتقد أننا آمنون جدًا. تم إصدار Python 3.4 في عام 2014 ، بينما تم إصدار OpenSSL 1.0.1a ، الذي أضاف TLSv1.2 ، في أبريل 2012. لذا من المحتمل أن تحتوي إصدارات التوزيعات من Python على شفرات قوية. الشيء الآخر هو أن كل إصدار من Python يتطلب إصدارًا معينًا من OpenSSL (على سبيل المثال ، يتطلب Python 3.7 OpenSSL 1.0.2 الذي أفهمه) ، لكنني لا أعرف بالضبط ما تتطلبه إصدارات Python.
بشكل عام يجب أن يتم إرشادي بواسطة OWASP. يقولون إن C- هي "قديمة ، توافق أوسع مع المتصفحات القديمة الحقيقية والمكتبات القديمة" - مع المكافأة الإضافية التي يمكن الاستشهاد بها كمصدر.
أيضًا ، لدى Python قائمة تشفير افتراضية خاصة بها: فهي لا تعود أبدًا إلى الإعداد الافتراضي لـ OpenSSL (والذي يبدو أنه DEFAULT:!aNULL:!eNULL
). يمكن الوصول إليه كـ ssl._DEFAULT_CIPHERS
على الرغم من أن ذلك داخلي / غير موثق ، لذا فإن طريقة الوصول إلى الإعدادات الافتراضية هي عدم استدعاء set_ciphers () على SSLContext.
لبايثون 3.6 _DEFAULT_CIPHERS
هو
'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'
في Python 3.7 يكون
'DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK'
مع تعليق يقول "DEFAULT: قائمة تشفير OpenSSL الافتراضية. منذ 1.0.2 القائمة في ترتيب معقول."
يبدو أن هذه الإعدادات ضيقة جدًا وبنفس روح OWASP.
هناك أيضًا _RESTRICTED_SERVER_CIPHERS
وهو مخصص للاستخدام في الخوادم (مثالي جدًا لـ gunicorn) وهو أضيق من _DEFAULT_CIPHERS
في بعض إصدارات Python ، لكن هذا داخلي ولا يُستخدم في أي مكان - ولكنه كان كذلك تم الاحتفاظ بها منذ 3.4.
لذا فإن الخيار 3 يكون افتراضيًا لمجموعة التشفير الافتراضية في Python.
السبب الوحيد لعدم القيام بذلك هو إذا كنا نعتقد أنه يمكننا شحن قائمة اليوم أكثر أمانًا من تلك الموجودة في إصدارات Python الأقدم ، أو أننا نريد الاشتراك في أحد مستويات OWASP الأكثر إحكامًا. بصراحة ، هذا هامشي جدًا.
التعليق الأكثر فائدة
أيضًا ، لدى Python قائمة تشفير افتراضية خاصة بها: فهي لا تعود أبدًا إلى الإعداد الافتراضي لـ OpenSSL (والذي يبدو أنه
DEFAULT:!aNULL:!eNULL
). يمكن الوصول إليه كـssl._DEFAULT_CIPHERS
على الرغم من أن ذلك داخلي / غير موثق ، لذا فإن طريقة الوصول إلى الإعدادات الافتراضية هي عدم استدعاء set_ciphers () على SSLContext.لبايثون 3.6
_DEFAULT_CIPHERS
هوفي Python 3.7 يكون
مع تعليق يقول "DEFAULT: قائمة تشفير OpenSSL الافتراضية. منذ 1.0.2 القائمة في ترتيب معقول."
يبدو أن هذه الإعدادات ضيقة جدًا وبنفس روح OWASP.
هناك أيضًا
_RESTRICTED_SERVER_CIPHERS
وهو مخصص للاستخدام في الخوادم (مثالي جدًا لـ gunicorn) وهو أضيق من_DEFAULT_CIPHERS
في بعض إصدارات Python ، لكن هذا داخلي ولا يُستخدم في أي مكان - ولكنه كان كذلك تم الاحتفاظ بها منذ 3.4.لذا فإن الخيار 3 يكون افتراضيًا لمجموعة التشفير الافتراضية في Python.
السبب الوحيد لعدم القيام بذلك هو إذا كنا نعتقد أنه يمكننا شحن قائمة اليوم أكثر أمانًا من تلك الموجودة في إصدارات Python الأقدم ، أو أننا نريد الاشتراك في أحد مستويات OWASP الأكثر إحكامًا. بصراحة ، هذا هامشي جدًا.