[SSPCPP-29] TLS connections from SP should not use weak cryptography Created: 31/Jul/07 Updated: 24/Jan/11 Resolved: 24/Jan/11 Status: Project: Component/s: Affects Version/s: Fix Version/s: Closed Shibboleth SP - C++ Request Processing 2.0a2 Type: Reporter: Resolution: Labels: Remaining Estimate: Time Spent: Original Estimate: Improvement Ian Young Fixed None Not Specified 2.0 Priority: Assignee: Minor Scott Cantor Not Specified Not Specified Multiple Operating System: Multiple CPU Type: C/C++ Compiler: Multiple Multiple Web Server: Description When the SP makes a TLS connection back to the IdP, for example for artifact resolution or an attribute query, it does so offering a list of cipher suites that I assume is just a default bubbling up from a lower-level library: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039) TLS_DHE_DSS_WITH_AES_256_CBC_SHA (0x0038) TLS_RSA_WITH_AES_256_CBC_SHA (0x0035) TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (0x0016) TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA (0x0013) TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a) TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033) TLS_DHE_DSS_WITH_AES_128_CBC_SHA (0x0032) TLS_RSA_WITH_AES_128_CBC_SHA (0x002f) TLS_DHE_DSS_WITH_RC4_128_SHA (0x0066) TLS_RSA_WITH_RC4_128_SHA (0x0005) TLS_RSA_WITH_RC4_128_MD5 (0x0004) TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA (0x0063) TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA (0x0062) TLS_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 (0x0061) TLS_DHE_RSA_WITH_DES_CBC_SHA (0x0015) TLS_DHE_DSS_WITH_DES_CBC_SHA (0x0012) TLS_RSA_WITH_DES_CBC_SHA (0x0009) TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA (0x0065) TLS_RSA_EXPORT1024_WITH_RC4_56_SHA (0x0064) TLS_RSA_EXPORT1024_WITH_RC4_56_MD5 (0x0060) TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA (0x0014) TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA (0x0011) TLS_RSA_EXPORT_WITH_DES40_CBC_SHA (0x0008) TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 (0x0006) TLS_RSA_EXPORT_WITH_RC4_40_MD5 (0x0003) About half of these cipher suites (the ones after the blank line above) are characterised by "openssl ciphers" (once you map the names across) as either "LOW" or "EXPORT", which is to say weak through to pathetic. I think that, at least by default, it would be better for a connection to fail than for these cipher suites to be used, particularly the 40-bit ones at the end. Shibboleth 1.3 appears to have the same characteristics as Shibboleth 2.0a2. This is pretty low risk, so I haven't marked it as a vulnerabilty. For the weak cipher suites to be used with an IdP that was capable of using stronger cryptography, the IdP's Apache SSL settings would have to be pretty perverted. On the other hand, few people understand Apache SSL settings so I don't know whether that might actually be widespread. Comments Comment by Scott Cantor [ 31/Jul/07 ] libcurl has an option for passing through an openssl cipher list. If you could determine what the list should initially be, it would be helpful. Comment by Scott Cantor [ 01/Aug/07 ] I'm going to need a shower after this code is done, but I'm going to open up a generic setter to pass arbitrary options and values into the transport object, and then I'll be able to support any libcurl option as a pass-thru. Should address people needing outbound proxy support also, among a million other use cases. Comment by Scott Cantor [ 02/Aug/07 ] If you have a way to test this, I'd like to see what the client end does with this change to the CURLPool::get method in soap/impl/CURLSOAPTransport.cpp: // curl_easy_setopt(handle,CURLOPT_SSLVERSION,3); curl_easy_setopt(handle,CURLOPT_SSL_CIPHER_LIST,"HIGH:MEDIUM:!SSLv2"); When I looked at the docs again, I realized my code was disallowing TLSv1 because all I could do was set the version to use, not disable SSLv2. I had been selecting SSLv3 as a compromise. If this works, I want to see it disallow any SSLv2 ciphers, thereby disabling v2 while also forcing 128 bit encryption. That would be the best default for now, and if I can get the passthru working, it can be overridden at runtime. I'll also patch the old opensaml code with this change if it gives us reasonable behavior. Comment by Ian Young [ 02/Aug/07 ] Sorry for slow response, I've been away in meetings for a couple of days. I think the cipher spec you're suggesting ("HIGH:MEDIUM:!SSLv2") would permit ciphers which didn't do authentication, which seems unlikely to be what we want. You could eliminate those by adding ":!aNULL" to your spec. ":!ADH" is currently equivalent to that. Another way of getting the same list (according to openssl ciphers -v) would be: ALL:!aNULL:!LOW:!EXPORT:!SSLv2 Read as: start with everything except ciphers with no encryption, ordered by strength. Remove noauthentication ciphers, remove low strength ciphers, remove export ciphers, remove SSLv2 ciphers. Comes to the same thing. I'll make a build environment in the next couple of days and use that to verify what each of these results in. Comment by Scott Cantor [ 02/Aug/07 ] That's fine, I'm not too worried about the string details yet, my primary concern is whether turning off SSLv2 in the cipher list will work. We'll have to have the server end confine itself to v2 as a test and make sure it won't connect. I can test that, but how are you getting this cipher list out at runtime? ssldump or something? Comment by Ian Young [ 02/Aug/07 ] Same idea as ssldump, I guess. I'm using Wireshark (http://www.wireshark.org/) running on the same (virtual) CentOS 5 machine as the SP. Wireshark is available as part of that distribution. Some examples of what you get out of wireshark for SSL here, from a session I had trying to figure out something odd that happened to me with Firefox 2.0: http://www.iay.org.uk/blog/2007/07/firefox_cipher.html Comment by Ian Young [ 03/Aug/07 ] The answer to your question seems to be that merely removing the SSLv2 ciphers from the cipher list does not in itself prevent the SSL V2 protocol from being used. I made this change: // curl_easy_setopt(handle,CURLOPT_SSLVERSION,3); curl_easy_setopt(handle,CURLOPT_SSL_CIPHER_LIST,"HIGH:MEDIUM:!SSLv2"); After rebuilding and reinstalling xmltooling the SP callback starts with the following: Secure Socket Layer SSLv2 Record Layer: Client Hello Length: 73 Handshake Message Type: Client Hello (1) Version: TLS 1.0 (0x0301) Cipher Spec Length: 48 Session ID Length: 0 Challenge Length: 16 Cipher Specs (16 specs) Cipher Spec: TLS_DH_anon_WITH_AES_256_CBC_SHA (0x00003a) Cipher Spec: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x000039) Cipher Spec: TLS_DHE_DSS_WITH_AES_256_CBC_SHA (0x000038) Cipher Spec: TLS_RSA_WITH_AES_256_CBC_SHA (0x000035) Cipher Spec: TLS_DH_anon_WITH_AES_128_CBC_SHA (0x000034) Cipher Spec: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x000033) Cipher Spec: TLS_DHE_DSS_WITH_AES_128_CBC_SHA (0x000032) Cipher Spec: TLS_RSA_WITH_AES_128_CBC_SHA (0x00002f) Cipher Spec: TLS_DH_anon_WITH_3DES_EDE_CBC_SHA (0x00001b) Cipher Spec: TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (0x000016) Cipher Spec: TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA (0x000013) Cipher Spec: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x00000a) Cipher Spec: TLS_DHE_DSS_WITH_RC4_128_SHA (0x000066) Cipher Spec: TLS_DH_anon_WITH_RC4_128_MD5 (0x000018) Cipher Spec: TLS_RSA_WITH_RC4_128_SHA (0x000005) Cipher Spec: TLS_RSA_WITH_RC4_128_MD5 (0x000004) Challenge This seems to be an SSL V2 client hello, which presumably means that we'd be able to talk to an SSL V2 server that happened to support one of those cipher suites. I think we'd also be vulnerable to the SSL V2 attacks. So, not good. Interestingly, though, the lack of an SSLVERSION option has meant that although the SP is prepared to negotiate SSL V2 as a lower bound, it is giving a version number indicating TLS V1.0 which means that TLS 1.0 is the upper bound, and that's what I end up seeing negotiated against my IdP. As expected, the list also has anonymous suites (DH_anon) in it, which we don't want. I confirmed that the string I suggested above does remove those four. Finally, using this... curl_easy_setopt(handle,CURLOPT_SSLVERSION,3); curl_easy_setopt(handle,CURLOPT_SSL_CIPHER_LIST,"ALL:!aNULL:!LOW:!EXPORT:!SSLv2"); ...resulted in the following Client Hello: Secure Socket Layer SSLv3 Record Layer: Handshake Protocol: Client Hello Content Type: Handshake (22) Version: SSL 3.0 (0x0300) Length: 68 Handshake Protocol: Client Hello Handshake Type: Client Hello (1) Length: 64 Version: SSL 3.0 (0x0300) Random gmt_unix_time: Aug 3, 2007 16:41:55.000000000 random_bytes: 6CFF08B3E9DF6FDCACE5F644C1601F33E8A6F981A48D2E67... Session ID Length: 0 Cipher Suites Length: 24 Cipher Suites (12 suites) Cipher Suite: TLS_DHE_DSS_WITH_RC4_128_SHA (0x0066) Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039) Cipher Suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA (0x0038) Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035) Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033) Cipher Suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA (0x0032) Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f) Cipher Suite: TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (0x0016) Cipher Suite: TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA (0x0013) Cipher Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a) Cipher Suite: TLS_RSA_WITH_RC4_128_SHA (0x0005) Cipher Suite: TLS_RSA_WITH_RC4_128_MD5 (0x0004) Compression Methods Length: 2 Compression Methods (2 methods) Compression Method: ZLIB (1) Compression Method: null (0) The explicit SSLVERSION seems to have set both a lower and upper bound here, and SSL V3 is what ends up being negotiated, not TLS 1.0. Similarly, this: curl_easy_setopt(handle,CURLOPT_SSLVERSION,CURL_SSLVERSION_TLSv1); curl_easy_setopt(handle,CURLOPT_SSL_CIPHER_LIST,"ALL:!aNULL:!LOW:!EXPORT:!SSLv2"); results in a TLS V1.0 request, making TLS V1.0 both a lower and upper bound. Enough browsing packet dumps for one day, I think. Comment by Scott Cantor [ 03/Aug/07 ] Ok, thanks, I was afraid of that. I'll have to stick with SSLv3 and let people override it to TLS using the new option feature, I guess. I'll correct the cipher list default and close the bug once I test the new features. If openssl has a way to turn off just v2 (which I know is true on the server side), I can probably convince Daniel to add that to libcurl. Comment by Scott Cantor [ 03/Aug/07 ] Patched with new default ciphers, also patched opensaml-1.1 branch. Comment by Scott Cantor [ 24/Jan/11 ] Reopening to update fix version. Generated at Tue Feb 09 13:03:00 EST 2016 using JIRA 7.0.10#70120sha1:37e3d7a6fc4d580639533e7f7c232c925e554a6a.