classification
Title: Python SSL Stack doesn't have a Secure Default set of ciphers
Type: security Stage: resolved
Components: Library (Lib) Versions: Python 3.2, Python 3.3, Python 2.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: gregory.p.smith, haypo, jcea, naif, pitrou, python-dev
Priority: normal Keywords: patch

Created on 2011-12-19 11:00 by naif, last changed 2012-01-04 01:31 by pitrou. This issue is now closed.

Files
File name Uploaded Description Edit
default_ciphers.patch pitrou, 2011-12-19 12:16
Messages (33)
msg149839 - (view) Author: naif (naif) Date: 2011-12-19 11:00
By default the Python SSL/TLS Stack (client/server) expose unsecure protocols (SSLv2) and unsecure ciphers (EXPORT 40bit DES).

This ticket is about defining a set of secure ciphers that should also provide maximum performance and compatibility, in order to allow any Python coder to use a Secure SSL/TLS stack without the need to became a Crypto Experts.

The discussion come from ticket http://bugs.python.org/issue13627 .

The proposal is to involve a discussion from the Tor Project (mailing list Tor-Talk & Tor-Dev) to define rationally a default set of ciphers/protocol for Python SSL/TLS from the Cryptography point of view .
msg149842 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-12-19 11:17
As I said, I don't think maintaining an explicit list of ciphers ourselves is reasonable, since there are no crypto experts (AFAICT) amongst the Python core developers.

Also, maintaining an explicit list of ciphers means people wouldn't benefit automatically from new ciphers unless Python itself is modified.

However, as I've proposed on issue13627, we could call set_ciphers("HIGH") by default. This excludes legacy ciphers (such as RC4, DES) without having us maintain an explicit list.
msg149844 - (view) Author: naif (naif) Date: 2011-12-19 11:32
From Antoine Pitrou (pitrou):
> Why don't you simple define your own default ciphers and call the
> set_ciphers() method?
> That said, we could perhaps call set_ciphers("HIGH") by default. This
> excludes legacy ciphers (such as RC4, DES) without having us maintain an
> explicit list.

I would suggest to follow a future proof approach that would consider:
* Disable SSLv2 (no one support it anymore)
* Enable Elliptic Curve Crypto and provide it as a priority (maximum security with strong performance gain)
* Enable Perfect Forward Secrecy ciphers first (DH ephemeral DHE)

* Provide an ordered cipher list for TLSv1
 - First ECC/DHE ciphers (Future Proof, PFS, with maximum performance)
 - Second DHE ciphers (Non-future proof, PFS, less performance)
 - Third TLSv1 AES ciphers (AES-128/AES-256, max compatibility, max performance)

* Then provide an ordered cipher list for SSLv3 (No AES support)
 - First 3DES DHE ciphers (PFS security)
 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA       EDH-RSA-DES-CBC3-SHA

 - Second 3DES non-DHE cipher 
 SSL_RSA_WITH_3DES_EDE_CBC_SHA           DES-CBC3-SHA

 - Third RC4 based encryption
 SSL_RSA_WITH_RC4_128_SHA


That way (but this is an approach to be discussed) we will pick-up a set of widely secure ciphers, high performance ciphers, highly compatible ciphers, but with a selection logic that's optimized for existing set of application and servers.

Or eventually hide that complexity for the Python developers by providing a set of "pre-configured" profiles to be used?

I always find ppl having difficulties in dealing with SSL/TLS, as a result SSL/TLS configuration it's often "by default" .
msg149845 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-12-19 12:04
Actually, it seems we want 'HIGH:!aNULL:!eNULL' to avoid non-encrypted and non-authenticated ciphers.

> That way (but this is an approach to be discussed) we will pick-up
> a set of widely secure ciphers

Please read my message above and understand this faces us with a number of maintenance problems which can actually *decrease* security.
msg149846 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-12-19 12:16
Here is a possible patch for 3.2.
Probably needs a doc addition as well.
msg149847 - (view) Author: naif (naif) Date: 2011-12-19 12:19
Ok for:
'HIGH:!aNULL:!eNULL'

but also:
- Disable SSLv2
- Enable ECC/ECDHE by default
- Enable DH/DHE by default

With this in place, i would then suggest to see which is the "Default ordered list of ciphers" with an SSL cipher scanner/wireshark.

Then we would be able to know if the "default order" for the ciphers is reasonable or if we would need to manually organize it to have a preferred selection that consider security and performance, while keeping always compatibility.

What do you think of an approach like this?
msg149849 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-12-19 12:33
> - Disable SSLv2

It should be disabled automatically since the SSLv2 cipher suites are not part of "HIGH": see http://www.openssl.org/docs/apps/ciphers.html#SSL_v2_0_cipher_suites_

> - Enable ECC/ECDHE by default
> - Enable DH/DHE by default

These both require parameters. I think adding simple instructions in the documentation would go a long way towards helping users. It would also probably be more instructive than silently choosing default values.

(after all, for ECDHE it's a one-line addition; DHE needs a separate file so it's less immediate)

> With this in place, i would then suggest to see which is the "Default
> ordered list of ciphers" with an SSL cipher scanner/wireshark.

I'm not really able to do that. Perhaps you can help?
msg149853 - (view) Author: naif (naif) Date: 2011-12-19 12:52
To disable SSLv2 you must specifically disable it.

Look, i tried a server we're working on http://github.com/hellais/tor2web that's running on:

privacyresearch.infosecurity.ch port 8888

With 'HIGH:!aNULL:!eNULL' SSLv2 can connect:

openssl s_client -connect  privacyresearch.infosecurity.ch:8888 -ssl2

SSLv2, Cipher is DES-CBC3-MD5

So it negotiated SSLv2 with 3DES that's not a good choice, SSLv2 must be disabled.

We must disable SSLv1 with !SSLv2, for example i am using just now 'HIGH:!aNULL:!eNULL:!SSLv2:@STRENGTH' .

Trying to connect with SSLv2 fail:
openssl s_client -connect  privacyresearch.infosecurity.ch:8888 -ssl2
140735092141340:error:1406D0B8:SSL routines:GET_SERVER_HELLO:no cipher list:s2_clnt.c:450:

Trying to connect by default, it select a strong cipher (i still didn't setup the dh/stuff):

openssl s_client -connect  privacyresearch.infosecurity.ch:8888

Connect with: TLSv1/SSLv3, Cipher is AES256-SHA
msg149856 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-12-19 13:02
> We must disable SSLv1 with !SSLv2, for example i am using just now
> 'HIGH:!aNULL:!eNULL:!SSLv2:@STRENGTH' .

Ok, thanks for the investigation. I think "HIGH:!aNULL:!eNULL:!SSLv2" is
sufficient.
msg149857 - (view) Author: naif (naif) Date: 2011-12-19 13:03
Yes, i can do the test for the ordered set of ciphers with all the patches in-place, can build a custom python 3.2 with the patch applied.

I would suggest to try to keep  ECC/ECDH/ECDHE enabled, conceptually we would like to have ECDHE as the first ciphers because it's the most modern, performance and secure.

For DH, you say that it require some file, but looking at mod_ssl Changelog it say:
      The reason was that mod_ssl's temporary RSA keys and DH parameters
      were stored in the persistent memory pool directly as OpenSSL's
      RSA and DH structures.

I mean, when i install Apache with SSL, from the system administrator point of view, i never have to create a file somewhere in order to have that ciphers.

Maybe also DH/EDH stuff can be done "in memory"?
msg149858 - (view) Author: naif (naif) Date: 2011-12-19 13:08
About ECDHE use as a default, prioritized key exchange method, google is using it along with RC4:
http://www.julianevansblog.com/2011/11/https-encryption-increased-for-gmail-and-google.html
msg149859 - (view) Author: naif (naif) Date: 2011-12-19 13:31
We could also disable all the ciphers that use MD5 for authentication:

MD5 has been disabled for SSL use due to it's weakness by:

- Firefox (All mozilla products now refuse any MD5 ciphers)
https://www.thesslstore.com/blog/index.php/firefox-to-stop-supporting-md5-based-ssl/
- Duracon by Jacob Appelbaum (Tor Project)
https://github.com/ioerror/duraconf

"HIGH:!aNULL:!eNULL:!SSLv2:!MD5" would do the magic, so we update the default to a modern, yet compatible set of SSL ciphers supported.

I don't want in any case to break compatibilities, but by default a software, should not support vulnerable, weak ciphers and this seems a good compromise.

Then the last fine tuning would be have the right preferred orders of ciphers to always prefer ECDHE (if available).
msg149860 - (view) Author: naif (naif) Date: 2011-12-19 13:37
It would be also useful to "Sort" the order of ciphers by it's strength.

This is done by the parameter @STRENGTH" :

From http://www.openssl.org/docs/apps/ciphers.html

"Additionally the cipher string @STRENGTH can be used at any point to sort the current cipher list in order of encryption algorithm key length."

In that case the default cipher string would become:
"HIGH:!aNULL:!eNULL:!SSLv2:!MD5:@STRENGTH"

The logic for third party developers could be explained as:

Only =>128bit ciphers
Disable unauthenticated ciphers
Disable SSLv2 protocol
Disable weak MD5 hash as authentication
Sort the cipher preferences by it's strength
msg149861 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-12-19 13:48
> MD5 has been disabled for SSL use due to it's weakness by:

Apparently MD5 is already disabled by "HIGH:!SSLv2".
msg149862 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-12-19 13:50
> I would suggest to try to keep  ECC/ECDH/ECDHE enabled, conceptually
> we would like to have ECDHE as the first ciphers because it's the most
> modern, performance and secure.

However, this will also divide performance by a large factor (from 2x to
4x apparently).

> Maybe also DH/EDH stuff can be done "in memory"?

Yes, there are also APIs for that, but you still have to provide magic
numbers (or have Python provide them).
msg149863 - (view) Author: naif (naif) Date: 2011-12-19 13:55
I confirm, tested "HIGH:!SSLv2" and MD5 cannot be negotiated.
msg149866 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-12-19 14:54
> About ECDHE use as a default, prioritized key exchange method, google
> is using it along with RC4:

Hmmm... do note that RC4 is disabled with "HIGH".
msg149977 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-12-21 10:13
I think we should relax the constraints a bit (RC4 seems ok for TLS/SSL use (*)) and therefore suggest we settle on "DEFAULT:!LOW:!EXPORT:!aNULL:!eNULL:!SSLv2".

(OpenSSL's default is "DEFAULT:!aNULL:!eNULL", so we're really disabling weak ciphers)

(*) Wikipedia even notes: “RC4, being a stream cipher, is the only common cipher which is immune[7] to the 2011 BEAST attack on TLS 1.0, which exploits a known weakness in the way cipher block chaining mode is used with all of the other ciphers supported by TLS 1.0, which are all block ciphers”
msg150008 - (view) Author: naif (naif) Date: 2011-12-21 16:16
Well, if you do:
"DEFAULT:!LOW:!EXPORT:!aNULL:!eNULL:!SSLv2" ciphers enabled are
ECDHE-RSA-AES256-SHA    SSLv3 Kx=ECDH     Au=RSA  Enc=AES(256)  Mac=SHA1
ECDHE-ECDSA-AES256-SHA  SSLv3 Kx=ECDH     Au=ECDSA Enc=AES(256)  Mac=SHA1
DHE-RSA-AES256-SHA      SSLv3 Kx=DH       Au=RSA  Enc=AES(256)  Mac=SHA1
DHE-DSS-AES256-SHA      SSLv3 Kx=DH       Au=DSS  Enc=AES(256)  Mac=SHA1
DHE-RSA-CAMELLIA256-SHA SSLv3 Kx=DH       Au=RSA  Enc=Camellia(256) Mac=SHA1
DHE-DSS-CAMELLIA256-SHA SSLv3 Kx=DH       Au=DSS  Enc=Camellia(256) Mac=SHA1
ECDH-RSA-AES256-SHA     SSLv3 Kx=ECDH/RSA Au=ECDH Enc=AES(256)  Mac=SHA1
ECDH-ECDSA-AES256-SHA   SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=AES(256)  Mac=SHA1
AES256-SHA              SSLv3 Kx=RSA      Au=RSA  Enc=AES(256)  Mac=SHA1
CAMELLIA256-SHA         SSLv3 Kx=RSA      Au=RSA  Enc=Camellia(256) Mac=SHA1
PSK-AES256-CBC-SHA      SSLv3 Kx=PSK      Au=PSK  Enc=AES(256)  Mac=SHA1
ECDHE-RSA-DES-CBC3-SHA  SSLv3 Kx=ECDH     Au=RSA  Enc=3DES(168) Mac=SHA1
ECDHE-ECDSA-DES-CBC3-SHA SSLv3 Kx=ECDH     Au=ECDSA Enc=3DES(168) Mac=SHA1
EDH-RSA-DES-CBC3-SHA    SSLv3 Kx=DH       Au=RSA  Enc=3DES(168) Mac=SHA1
EDH-DSS-DES-CBC3-SHA    SSLv3 Kx=DH       Au=DSS  Enc=3DES(168) Mac=SHA1
ECDH-RSA-DES-CBC3-SHA   SSLv3 Kx=ECDH/RSA Au=ECDH Enc=3DES(168) Mac=SHA1
ECDH-ECDSA-DES-CBC3-SHA SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=3DES(168) Mac=SHA1
DES-CBC3-SHA            SSLv3 Kx=RSA      Au=RSA  Enc=3DES(168) Mac=SHA1
PSK-3DES-EDE-CBC-SHA    SSLv3 Kx=PSK      Au=PSK  Enc=3DES(168) Mac=SHA1
ECDHE-RSA-AES128-SHA    SSLv3 Kx=ECDH     Au=RSA  Enc=AES(128)  Mac=SHA1
ECDHE-ECDSA-AES128-SHA  SSLv3 Kx=ECDH     Au=ECDSA Enc=AES(128)  Mac=SHA1
DHE-RSA-AES128-SHA      SSLv3 Kx=DH       Au=RSA  Enc=AES(128)  Mac=SHA1
DHE-DSS-AES128-SHA      SSLv3 Kx=DH       Au=DSS  Enc=AES(128)  Mac=SHA1
DHE-RSA-SEED-SHA        SSLv3 Kx=DH       Au=RSA  Enc=SEED(128) Mac=SHA1
DHE-DSS-SEED-SHA        SSLv3 Kx=DH       Au=DSS  Enc=SEED(128) Mac=SHA1
DHE-RSA-CAMELLIA128-SHA SSLv3 Kx=DH       Au=RSA  Enc=Camellia(128) Mac=SHA1
DHE-DSS-CAMELLIA128-SHA SSLv3 Kx=DH       Au=DSS  Enc=Camellia(128) Mac=SHA1
ECDH-RSA-AES128-SHA     SSLv3 Kx=ECDH/RSA Au=ECDH Enc=AES(128)  Mac=SHA1
ECDH-ECDSA-AES128-SHA   SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=AES(128)  Mac=SHA1
AES128-SHA              SSLv3 Kx=RSA      Au=RSA  Enc=AES(128)  Mac=SHA1
SEED-SHA                SSLv3 Kx=RSA      Au=RSA  Enc=SEED(128) Mac=SHA1
CAMELLIA128-SHA         SSLv3 Kx=RSA      Au=RSA  Enc=Camellia(128) Mac=SHA1
IDEA-CBC-SHA            SSLv3 Kx=RSA      Au=RSA  Enc=IDEA(128) Mac=SHA1
PSK-AES128-CBC-SHA      SSLv3 Kx=PSK      Au=PSK  Enc=AES(128)  Mac=SHA1
ECDHE-RSA-RC4-SHA       SSLv3 Kx=ECDH     Au=RSA  Enc=RC4(128)  Mac=SHA1
ECDHE-ECDSA-RC4-SHA     SSLv3 Kx=ECDH     Au=ECDSA Enc=RC4(128)  Mac=SHA1
ECDH-RSA-RC4-SHA        SSLv3 Kx=ECDH/RSA Au=ECDH Enc=RC4(128)  Mac=SHA1
ECDH-ECDSA-RC4-SHA      SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=RC4(128)  Mac=SHA1
RC4-SHA                 SSLv3 Kx=RSA      Au=RSA  Enc=RC4(128)  Mac=SHA1
RC4-MD5                 SSLv3 Kx=RSA      Au=RSA  Enc=RC4(128)  Mac=MD5 
PSK-RC4-SHA             SSLv3 Kx=PSK      Au=PSK  Enc=RC4(128)  Mac=SHA1


If we want to start from the "DEFAULT" than we should probably disable:
- PSK
- CAMELLIA
- MD5
- IDEA
- SEED

That way:
openssl ciphers -v 'DEFAULT:!LOW:!EXPORT:!aNULL:!eNULL:!SSLv2:!PSK:!CAMELLIA:!MD5:!IDEA!SEED'

ECDHE-RSA-AES256-SHA    SSLv3 Kx=ECDH     Au=RSA  Enc=AES(256)  Mac=SHA1
ECDHE-ECDSA-AES256-SHA  SSLv3 Kx=ECDH     Au=ECDSA Enc=AES(256)  Mac=SHA1
DHE-RSA-AES256-SHA      SSLv3 Kx=DH       Au=RSA  Enc=AES(256)  Mac=SHA1
DHE-DSS-AES256-SHA      SSLv3 Kx=DH       Au=DSS  Enc=AES(256)  Mac=SHA1
ECDH-RSA-AES256-SHA     SSLv3 Kx=ECDH/RSA Au=ECDH Enc=AES(256)  Mac=SHA1
ECDH-ECDSA-AES256-SHA   SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=AES(256)  Mac=SHA1
AES256-SHA              SSLv3 Kx=RSA      Au=RSA  Enc=AES(256)  Mac=SHA1
ECDHE-RSA-DES-CBC3-SHA  SSLv3 Kx=ECDH     Au=RSA  Enc=3DES(168) Mac=SHA1
ECDHE-ECDSA-DES-CBC3-SHA SSLv3 Kx=ECDH     Au=ECDSA Enc=3DES(168) Mac=SHA1
EDH-RSA-DES-CBC3-SHA    SSLv3 Kx=DH       Au=RSA  Enc=3DES(168) Mac=SHA1
EDH-DSS-DES-CBC3-SHA    SSLv3 Kx=DH       Au=DSS  Enc=3DES(168) Mac=SHA1
ECDH-RSA-DES-CBC3-SHA   SSLv3 Kx=ECDH/RSA Au=ECDH Enc=3DES(168) Mac=SHA1
ECDH-ECDSA-DES-CBC3-SHA SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=3DES(168) Mac=SHA1
DES-CBC3-SHA            SSLv3 Kx=RSA      Au=RSA  Enc=3DES(168) Mac=SHA1
ECDHE-RSA-AES128-SHA    SSLv3 Kx=ECDH     Au=RSA  Enc=AES(128)  Mac=SHA1
ECDHE-ECDSA-AES128-SHA  SSLv3 Kx=ECDH     Au=ECDSA Enc=AES(128)  Mac=SHA1
DHE-RSA-AES128-SHA      SSLv3 Kx=DH       Au=RSA  Enc=AES(128)  Mac=SHA1
DHE-DSS-AES128-SHA      SSLv3 Kx=DH       Au=DSS  Enc=AES(128)  Mac=SHA1
ECDH-RSA-AES128-SHA     SSLv3 Kx=ECDH/RSA Au=ECDH Enc=AES(128)  Mac=SHA1
ECDH-ECDSA-AES128-SHA   SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=AES(128)  Mac=SHA1
AES128-SHA              SSLv3 Kx=RSA      Au=RSA  Enc=AES(128)  Mac=SHA1
ECDHE-RSA-RC4-SHA       SSLv3 Kx=ECDH     Au=RSA  Enc=RC4(128)  Mac=SHA1
ECDHE-ECDSA-RC4-SHA     SSLv3 Kx=ECDH     Au=ECDSA Enc=RC4(128)  Mac=SHA1
ECDH-RSA-RC4-SHA        SSLv3 Kx=ECDH/RSA Au=ECDH Enc=RC4(128)  Mac=SHA1
ECDH-ECDSA-RC4-SHA      SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=RC4(128)  Mac=SHA1
RC4-SHA                 SSLv3 Kx=RSA      Au=RSA  Enc=RC4(128)  Mac=SHA1

What do you think?
msg150009 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-12-21 16:29
> If we want to start from the "DEFAULT" than we should probably disable:
> - PSK
> - CAMELLIA
> - MD5
> - IDEA
> - SEED

Why do you want to disable all these?
msg150015 - (view) Author: naif (naif) Date: 2011-12-21 16:59
Well,

with your latest proposal 'HIGH:!aNULL:!eNULL:!SSLv2' :
- MD5 was disabled
- IDEA was disabled
- SEED was disabled

Then we realized that RC4 could be a cipher to be leaved enabled, so the new proposal starting from 'DEFAULT'.

While i don't like RC4 because it's not FIPS-140 compliant (https://www.mozilla.org/projects/security/pki/nss/ssl/fips-ssl-ciphersuites.html) i understand that we may want to keep it.

I would suggest by default to keep disabled also CAMELIA and PSK because almost no one use it, they are just into the standard like many ciphers.

Generally speaking, as a concept to define a default we could:
- Start from a FIPS-140 compliant SSL stack
- Open some additional ciphers for compatibility reason (for example RC4-SHA)

What do you think about such approach?

-naif
msg150018 - (view) Author: Gregory P. Smith (gregory.p.smith) * (Python committer) Date: 2011-12-21 17:09
Why make this decision ourselves at all? Copy what Mozilla and Chromium do
by default.
msg150020 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-12-21 17:22
> Why make this decision ourselves at all? Copy what Mozilla and Chromium do
> by default.

If that translates to an explicit list of ciphers it will be a pain to
maintain. Using a generic OpenSSL string such as "DEFAULT:!LOW:[etc.]"
means OpenSSL mostly does the maintenance for us.
msg150021 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-12-21 17:26
> with your latest proposal 'HIGH:!aNULL:!eNULL:!SSLv2' :
> - MD5 was disabled
> - IDEA was disabled
> - SEED was disabled

That was the consequence of it, but that wasn't an explicit goal.

> Generally speaking, as a concept to define a default we could:
> - Start from a FIPS-140 compliant SSL stack
> - Open some additional ciphers for compatibility reason (for example
> RC4-SHA)
> 
> What do you think about such approach?

As I already said, the more sophisticated the approach, the more tedious
the maintenance.
msg150023 - (view) Author: naif (naif) Date: 2011-12-21 17:31
Well, my concept is that it would be reasonable to use what people consider secure.

SSL/TLS are security protocol.

Some combination of the protocol configuration (ciphers/hash/key exchange) are:
- known to be insecure
- known to be secure
- known to be unused (like SEED, only used in South Korea by military applications) or PSK with almost no adoption
- Unknown (like CAMELIA, i don't find a single software using it)

The concept i would propose is to choose the ciphers that "known to be secure" by disabling everything else.
msg150025 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-12-21 17:36
> The concept i would propose is to choose the ciphers that "known to be
> secure" by disabling everything else.

I hate repeating myself, but who will maintain it?
msg150034 - (view) Author: STINNER Victor (haypo) * (Python committer) Date: 2011-12-21 19:03
> By default the Python SSL/TLS Stack (client/server) expose
> unsecure protocols (SSLv2) and unsecure ciphers (EXPORT 40bit DES).

If there is a problem, it should not be fixed in Python, but in the underlying library (OpenSSL) or in applications. Python only exposes features of the OpenSSL library. You should not see Python as an application but as a language: Python doesn't know what is your use case, or if you write a client or a server.

I suppose that OpenSSL has good reasons to still support weak algorithms like MD4 or SSLv2. Some operating systems, like Debian Sid, disable SSLv2 in the OpenSSL at the compilation.

If you consider that it is too complex to change the cipher list in a high level API (like http.client?), we may a ssl.DEFAULT_CIPHERS to allow an application to change the *default* cipher list.

SSLContext() requires a protocol, I suppose that the protocol is also by OpenSSL used in the negociation of the cipher list.

If we change the default behaviour, we should allow the user to get back the old behaviour (e.g. mark ssl._DEFAULT_CIPHERS as public in default_ciphers.patch).

--

IMO this issue is more a documentation issue: we should add a warning in the ssl module documentation, and maybe also in the documentation of modules using the ssl module (as we done for certificates for HTTPS).
msg150076 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-12-22 07:39
> > By default the Python SSL/TLS Stack (client/server) expose
> > unsecure protocols (SSLv2) and unsecure ciphers (EXPORT 40bit DES).
> 
> If there is a problem, it should not be fixed in Python, but in the
> underlying library (OpenSSL) or in applications. Python only exposes
> features of the OpenSSL library.

The ssl module's theoretical goal is to provide access to SSL features;
that it wraps OpenSSL APIs is mostly an implementation detail, although
it is true that the APIs resemble OpenSSL's in some places.

This is where we can have different policies: OpenSSL is a low-level
library with an exhaustive (if poorly documented) API; the ssl module is
more synthetic and slightly higher-level, and likely to be used by
crypto novices. As such, we can have a different set of default ciphers.

> You should not see Python as an application but as a language: Python
> doesn't know what is your use case, or if you write a client or a
> server.

This is why I would like to stay conservative when disabling ciphers:
disable the really weak ones, but avoid being too opinionated.

> If you consider that it is too complex to change the cipher list in a
> high level API (like http.client?), we may a ssl.DEFAULT_CIPHERS to
> allow an application to change the *default* cipher list.

Changing higher-level APIs means there are more places where the change
has to be done.

> SSLContext() requires a protocol, I suppose that the protocol is also
> by OpenSSL used in the negociation of the cipher list.

There are weak ciphers even in TLS1.

> If we change the default behaviour, we should allow the user to get
> back the old behaviour (e.g. mark ssl._DEFAULT_CIPHERS as public in
> default_ciphers.patch).

set_ciphers("something") is how you change ciphers. It is a public API.
But I wouldn't expect anyone to re-enable 56-bit DES ciphers: if we are
conservative with our choice of default ciphers, nobody should have
issues with it.

> IMO this issue is more a documentation issue: we should add a warning
> in the ssl module documentation, and maybe also in the documentation
> of modules using the ssl module (as we done for certificates for
> HTTPS).

Most ssl-using modules won't give the user access to such settings.
Besides, you can't expect someone using urllib.request() to know which
ciphers should be disabled. The library (either ssl or urllib or
http.client) should choose the right defaults.

I agree about documenting it in any case. But that doesn't mean we
shouldn't *also* set a reasonable default.
msg150081 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-12-22 08:50
For the record, here are the default ciphers in our Windows OpenSSL build:

Z:\openssl-1.0.0a>out64\openssl.exe ciphers -v
WARNING: can't open config file: /usr/local/ssl/openssl.cnf
ECDHE-RSA-AES256-SHA    SSLv3 Kx=ECDH     Au=RSA  Enc=AES(256)  Mac=SHA1
ECDHE-ECDSA-AES256-SHA  SSLv3 Kx=ECDH     Au=ECDSA Enc=AES(256)  Mac=SHA1
DHE-RSA-AES256-SHA      SSLv3 Kx=DH       Au=RSA  Enc=AES(256)  Mac=SHA1
DHE-DSS-AES256-SHA      SSLv3 Kx=DH       Au=DSS  Enc=AES(256)  Mac=SHA1
DHE-RSA-CAMELLIA256-SHA SSLv3 Kx=DH       Au=RSA  Enc=Camellia(256) Mac=SHA1
DHE-DSS-CAMELLIA256-SHA SSLv3 Kx=DH       Au=DSS  Enc=Camellia(256) Mac=SHA1
ECDH-RSA-AES256-SHA     SSLv3 Kx=ECDH/RSA Au=ECDH Enc=AES(256)  Mac=SHA1
ECDH-ECDSA-AES256-SHA   SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=AES(256)  Mac=SHA1
AES256-SHA              SSLv3 Kx=RSA      Au=RSA  Enc=AES(256)  Mac=SHA1
CAMELLIA256-SHA         SSLv3 Kx=RSA      Au=RSA  Enc=Camellia(256) Mac=SHA1
PSK-AES256-CBC-SHA      SSLv3 Kx=PSK      Au=PSK  Enc=AES(256)  Mac=SHA1
ECDHE-RSA-DES-CBC3-SHA  SSLv3 Kx=ECDH     Au=RSA  Enc=3DES(168) Mac=SHA1
ECDHE-ECDSA-DES-CBC3-SHA SSLv3 Kx=ECDH     Au=ECDSA Enc=3DES(168) Mac=SHA1
EDH-RSA-DES-CBC3-SHA    SSLv3 Kx=DH       Au=RSA  Enc=3DES(168) Mac=SHA1
EDH-DSS-DES-CBC3-SHA    SSLv3 Kx=DH       Au=DSS  Enc=3DES(168) Mac=SHA1
ECDH-RSA-DES-CBC3-SHA   SSLv3 Kx=ECDH/RSA Au=ECDH Enc=3DES(168) Mac=SHA1
ECDH-ECDSA-DES-CBC3-SHA SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=3DES(168) Mac=SHA1
DES-CBC3-SHA            SSLv3 Kx=RSA      Au=RSA  Enc=3DES(168) Mac=SHA1
PSK-3DES-EDE-CBC-SHA    SSLv3 Kx=PSK      Au=PSK  Enc=3DES(168) Mac=SHA1
ECDHE-RSA-AES128-SHA    SSLv3 Kx=ECDH     Au=RSA  Enc=AES(128)  Mac=SHA1
ECDHE-ECDSA-AES128-SHA  SSLv3 Kx=ECDH     Au=ECDSA Enc=AES(128)  Mac=SHA1
DHE-RSA-AES128-SHA      SSLv3 Kx=DH       Au=RSA  Enc=AES(128)  Mac=SHA1
DHE-DSS-AES128-SHA      SSLv3 Kx=DH       Au=DSS  Enc=AES(128)  Mac=SHA1
DHE-RSA-SEED-SHA        SSLv3 Kx=DH       Au=RSA  Enc=SEED(128) Mac=SHA1
DHE-DSS-SEED-SHA        SSLv3 Kx=DH       Au=DSS  Enc=SEED(128) Mac=SHA1
DHE-RSA-CAMELLIA128-SHA SSLv3 Kx=DH       Au=RSA  Enc=Camellia(128) Mac=SHA1
DHE-DSS-CAMELLIA128-SHA SSLv3 Kx=DH       Au=DSS  Enc=Camellia(128) Mac=SHA1
ECDH-RSA-AES128-SHA     SSLv3 Kx=ECDH/RSA Au=ECDH Enc=AES(128)  Mac=SHA1
ECDH-ECDSA-AES128-SHA   SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=AES(128)  Mac=SHA1
AES128-SHA              SSLv3 Kx=RSA      Au=RSA  Enc=AES(128)  Mac=SHA1
SEED-SHA                SSLv3 Kx=RSA      Au=RSA  Enc=SEED(128) Mac=SHA1
CAMELLIA128-SHA         SSLv3 Kx=RSA      Au=RSA  Enc=Camellia(128) Mac=SHA1
PSK-AES128-CBC-SHA      SSLv3 Kx=PSK      Au=PSK  Enc=AES(128)  Mac=SHA1
ECDHE-RSA-RC4-SHA       SSLv3 Kx=ECDH     Au=RSA  Enc=RC4(128)  Mac=SHA1
ECDHE-ECDSA-RC4-SHA     SSLv3 Kx=ECDH     Au=ECDSA Enc=RC4(128)  Mac=SHA1
ECDH-RSA-RC4-SHA        SSLv3 Kx=ECDH/RSA Au=ECDH Enc=RC4(128)  Mac=SHA1
ECDH-ECDSA-RC4-SHA      SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=RC4(128)  Mac=SHA1
RC4-SHA                 SSLv3 Kx=RSA      Au=RSA  Enc=RC4(128)  Mac=SHA1
RC4-MD5                 SSLv3 Kx=RSA      Au=RSA  Enc=RC4(128)  Mac=MD5
PSK-RC4-SHA             SSLv3 Kx=PSK      Au=PSK  Enc=RC4(128)  Mac=SHA1
EDH-RSA-DES-CBC-SHA     SSLv3 Kx=DH       Au=RSA  Enc=DES(56)   Mac=SHA1
EDH-DSS-DES-CBC-SHA     SSLv3 Kx=DH       Au=DSS  Enc=DES(56)   Mac=SHA1
DES-CBC-SHA             SSLv3 Kx=RSA      Au=RSA  Enc=DES(56)   Mac=SHA1
EXP-EDH-RSA-DES-CBC-SHA SSLv3 Kx=DH(512)  Au=RSA  Enc=DES(40)   Mac=SHA1 export
EXP-EDH-DSS-DES-CBC-SHA SSLv3 Kx=DH(512)  Au=DSS  Enc=DES(40)   Mac=SHA1 export
EXP-DES-CBC-SHA         SSLv3 Kx=RSA(512) Au=RSA  Enc=DES(40)   Mac=SHA1 export
EXP-RC2-CBC-MD5         SSLv3 Kx=RSA(512) Au=RSA  Enc=RC2(40)   Mac=MD5  export
EXP-RC4-MD5             SSLv3 Kx=RSA(512) Au=RSA  Enc=RC4(40)   Mac=MD5  export
msg150086 - (view) Author: naif (naif) Date: 2011-12-22 10:51
Regarding the mainteneance i expect that, if we make a future-proof choice, it would take at least 5 years before that someone will need to have other ciphers added.

Consider that a new cipher is standardized once every X year, and typically, if it get diffused/adopted (and not abbandoned or marginally used), it will happen in few other years.

The new ciphers will get into OpenSSL, so the proposed approach to:
- Start from default
- Disable anything that's
  - Unsecure/Weak
  - Not used/widely used

Would still means that, when OpenSSL library will add a new cipher because a new RFC will get out, for sure it will not be unsecure/weak. There are chance that it will not get used/widely used, in that case in some other year, we'll update the default disabled ciphers.

But such approach would provide very "low maintenance" because "not doing anything" can only create a situation where "more ciphers" get added by default (included in newer OpenSSL / new TLS RFC).

But those new ciphers will not be weak, even if not maintained.
msg150539 - (view) Author: Roundup Robot (python-dev) Date: 2012-01-03 21:51
New changeset 25c2d24e1b11 by Antoine Pitrou in branch '3.2':
Issue #13636: Weak ciphers are now disabled by default in the ssl module
http://hg.python.org/cpython/rev/25c2d24e1b11

New changeset ace54f5e75d7 by Antoine Pitrou in branch 'default':
Issue #13636: Weak ciphers are now disabled by default in the ssl module
http://hg.python.org/cpython/rev/ace54f5e75d7
msg150540 - (view) Author: Roundup Robot (python-dev) Date: 2012-01-03 22:00
New changeset f9122975fd80 by Antoine Pitrou in branch '2.7':
Issue #13636: Weak ciphers are now disabled by default in the ssl module
http://hg.python.org/cpython/rev/f9122975fd80
msg150566 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2012-01-04 01:31
I've committed a conservative version of the patch, plus a test.
History
Date User Action Args
2012-01-04 01:31:56pitrousetstatus: open -> closed
resolution: fixed
messages: + msg150566

stage: patch review -> resolved
2012-01-03 22:00:51python-devsetmessages: + msg150540
2012-01-03 21:51:42python-devsetnosy: + python-dev
messages: + msg150539
2011-12-22 10:51:06naifsetmessages: + msg150086
2011-12-22 08:50:19pitrousetmessages: + msg150081
2011-12-22 07:39:24pitrousetmessages: + msg150076
2011-12-21 19:03:51hayposetnosy: + haypo
messages: + msg150034
2011-12-21 17:36:22pitrousetmessages: + msg150025
2011-12-21 17:31:17naifsetmessages: + msg150023
2011-12-21 17:26:39pitrousetmessages: + msg150021
2011-12-21 17:22:15pitrousetmessages: + msg150020
2011-12-21 17:09:59gregory.p.smithsetmessages: + msg150018
2011-12-21 16:59:51naifsetmessages: + msg150015
2011-12-21 16:29:20pitrousetmessages: + msg150009
2011-12-21 16:16:32naifsetmessages: + msg150008
2011-12-21 10:13:49pitrousetmessages: + msg149977
2011-12-20 01:32:32jceasetnosy: + jcea
2011-12-19 14:54:42pitrousetmessages: + msg149866
2011-12-19 13:55:48naifsetmessages: + msg149863
2011-12-19 13:50:57pitrousetmessages: + msg149862
2011-12-19 13:48:17pitrousetmessages: + msg149861
2011-12-19 13:37:22naifsetmessages: + msg149860
2011-12-19 13:31:32naifsetmessages: + msg149859
2011-12-19 13:08:21naifsetmessages: + msg149858
2011-12-19 13:03:09naifsetmessages: + msg149857
2011-12-19 13:02:31pitrousetmessages: + msg149856
2011-12-19 12:52:59naifsetmessages: + msg149853
2011-12-19 12:33:46pitrousetmessages: + msg149849
2011-12-19 12:19:10naifsetmessages: + msg149847
2011-12-19 12:16:00pitrousetfiles: + default_ciphers.patch
versions: + Python 2.7
messages: + msg149846

keywords: + patch
stage: needs patch -> patch review
2011-12-19 12:04:29pitrousetmessages: + msg149845
2011-12-19 11:32:58naifsetmessages: + msg149844
2011-12-19 11:17:36pitrousetversions: - Python 2.6, Python 3.1, Python 2.7, Python 3.4
nosy: + gregory.p.smith, pitrou

messages: + msg149842

type: security
stage: needs patch
2011-12-19 11:00:07naifcreate