New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Default SSL ciphers setting disables the most secure ciphers #1966
Comments
Thank you for reporting this issue. We're absolutely well aware of this. Gunicorn has not had significant changes to its SSL support for a while. See #1933 and the issues linked in that discussion. In the meantime, if there is a more sensible default now that Gunicorn only supports Python 3.4+, please submit a pull request and I'd be glad to merge it. We're also considering pushing that minimum version higher, so if there's a higher minimum Python version that would enable an even more secure default, please post that information here to help drive that decision before the next release. |
The ciphers available (and the interpretation of the argument to If your question is "can we set a more secure default that always works in Python 3.4+" then the strict answer is "no" because it depends how you compiled Python. It may be possible to compile a recent Python against a very old OpenSSL that lacks strong ciphers, so requiring strong ciphers in gunicorn could mean SSL doesn't work at all. However, I think we're pretty safe. Python 3.4 was released in 2014, while OpenSSL 1.0.1a, which added TLSv1.2, was released in April 2012. So distro versions of Python will probably have strong ciphers. The other thing is that each Python release requires a certain OpenSSL version (eg. Python 3.7 requires OpenSSL 1.0.2 I understand), but I don't know exactly what Python versions require what. Overall I would have to be guided by OWASP. They say C- is "Legacy, widest compatibility to real old browsers and legacy libraries" - with the added bonus that they can be cited as the source. |
Also, Python has its own default cipher list: it never falls back to OpenSSL's default (which is apparently For Python 3.6
In Python 3.7 it's
with a comment saying "DEFAULT: OpenSSL's default cipher list. Since 1.0.2 the list is in sensible order." These settings seem to be pretty tight, and in the same spirit as the OWASP. There's also a So option 3 is default to Python's default cipher suite. The only reason not to do that is if we think we could ship a list today that is more secure than that in older Python versions, or that we want to opt-in to one of the even tighter OWASP levels. Honestly that's pretty marginal. |
The default for the --ciphers option is
TLSv1
.This value is a bad default, because it actively disables new, strong ciphers that are only available with TLSv1.2. In particular, there is no intersection between the set of ciphers configured by this default value and the ciphers rated A+ by OWASP:
This can lead to OpenSSL
NO_SHARED_CIPHER
errors for clients configured with high security settings.One solution would be to simply add TLSv1.2 ciphers to the set, by changing the default to the string
'TLSv1:TLSv1.2'
. This would add compatibility for clients configured with strict security settings, without breaking any existing users of gunicorn. However, this would leave weak ciphers in the set.A more secure option would be to pick one of the OWASP strings as a default, based on the described compatibility level. For example OWASP Cipher String C or C- would preserve wide compatibility while ruling out known-weak ciphers.
In either case, the documentation could be updated to recommend replacing the default with a stronger default based on expected usage, including a link to the OWASP page as a reference.
The text was updated successfully, but these errors were encountered: