8

With the recent buzz about the SSL BEAST vulnerability I wanted to try to improve the security of an SSL protected web site that is based on Tomcat 6. To that end, I tried the google approach of giving non Cipher Block Chaining (CBC) ciphers priority in my Tomcat server.xml file in the HTTP connector declaration:

ciphers="TLS_ECDHE_RSA_WITH_RC4_128_SHA,
         TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
         TLS_ECDH_RSA_WITH_RC4_128_SHA,
         TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
         TLS_RSA_WITH_RC4_128_SHA,
         TLS_RSA_WITH_RC4_128_MD5,
         TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
         TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
         TLS_RSA_WITH_AES_256_CBC_SHA,
         TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
         TLS_RSA_WITH_3DES_EDE_CBC_SHA,
         TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
         TLS_RSA_WITH_AES_128_CBC_SHA"

But Tomcat does not appear to use the order of the ciphers, but instead seems to select the best cipher based on key strength. Also SSL Labs indicates that my site does not show a cipher preference, whereas google.com does. I do not want to remove the 256 bit CBC ciphers in order to use the 128 bit RC4 cipher for fear of SSL incompatibilities. I am guessing that the cipher selection is done at the Java JSSE layer and not in Tomcat.

Does anyone know of a simple way to customize the priority/order of the SSL ciphers with the standard Tomcat HTTP connector? Is there a way to achieve this using a simple custom java class? Does the Tomcat APR connector and some openSSL configuration option offer an alternative. Is there some other simple way to do this?

Note that I realize that this attack requires cross site scripting or some other similar vulnerability, and so is not that serious (for my site). However, if there are easy steps to mitigate this attack, I will take them. Also, I do not want to introduce an Apache front end (assuming there is a way to do this in Apache) because of the extra complexity and therefor risk.

StackzOfZtuff
  • 1,842
  • 13
  • 21

4 Answers4

4

I have the same issue. It seems that we can't do what we want.
The Sun(Oracle) Java SSL implementation checks only the client side cipher suite order(priorities) and ignores the server side.

Related classes are:
sun.security.ssl.ServerHandshaker
sun.security.ssl.CipherSuite

On ServerHandshaker,
"private void chooseCipherSuite(ClientHello mesg)"
http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Modules-sun/security/sun/security/ssl/ServerHandshaker.java.htm

/*
 * Choose cipher suite from among those supported by client. Sets
 * the cipherSuite and keyExchange variables.
 */
private void chooseCipherSuite(ClientHello mesg) throws IOException {
    for (CipherSuite suite : mesg.getCipherSuites().collection()) {
        if (isEnabled(suite) == false) {
            continue;
        }
        if (doClientAuth == SSLEngineImpl.clauth_required) {
            if ((suite.keyExchange == K_DH_ANON) || (suite.keyExchange == K_ECDH_ANON)) {
                continue;
            }
        }
        if (trySetCipherSuite(suite) == false) {
            continue;
        }
        return;
    }
    fatalSE(Alerts.alert_handshake_failure,
                "no cipher suites in common");
}

We can see that it itelates cipher suites in the client hello message and chooses cipher suite.

Kanatoko
  • 41
  • 3
  • 2
    Java 8 supports server side cipher suite ordering. http://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#cipher_suite_preference Tomcat 8.0.21 or later can use this feature. – Kanatoko Apr 15 '15 at 08:34
4

For native/APR/OpenSSL connectors

As of Tomcat 6.0.37/7.0.30/8.0.x, the native/APR/OpenSSL-based connector supports the SSLHonorCipherOrder configuration setting which allows the server to have a specified order in which ciphers are chosen. That ordering is up to you and isn't based upon fuzzy definitions like "strength", since a high-bit cipher can be worse than a lower-bit cipher in certain situations.

For Java-based connectors (BIO, NIO, NIO2)

Tomcat 8.0.21 and later on Java 8 and later will use the server's preferred cipher-suite order if useServerCipherSuitesOrder is set to "true" (the default) for Java-based connectors.

Tomcat 7.0.60 and later on Java 8 and later will use the server's preferred cipher-suite order if useServerCipherSuitesOrder is set to "true" (the default) for Java-based connectors.

Tomcat 6 never had this capability for Java-based connectors; server-preferred ordering of cipher suites on Tomcat 6 will require the use of the APR/native connector.

Update 2022-09-22

A lot of things have changed since this question was first asked back in 2011 about Tomcat 6 or 7 running on probably Java 6, 7, or 8. All reasonably recent versions of both Java and Tomcat can do what you want, just read the appropriate documentation.

Christopher Schultz
  • 1,105
  • 2
  • 12
  • 22
  • Actually the default for `useServerCipherSuitesOrder` is based on the underlying JSSE implementation. With tomcat 9 the setting was changed to `honorCipherOrder` with `useServerCipherSuitesOrder` being an alias for the new setting and the default changed to `false`. https://tomcat.apache.org/tomcat-9.0-doc/config/http.html – dpr Sep 22 '22 at 19:47
  • 1
    The *current* (Tomcat 8.5 and later) default is based upon what Tomcat says it is. There is no fall-back to whatever JSSE thinks is a good idea; Tomcat will always either honor the server's cipher ordering or not. That setting was changed from `useServerCipherSuitesOrder` -> `honorCipherOrder` in Tomcat 8.5 when `` was introduced. The old name is still used on the `` for backward-compatibility. For completeness, the BIO connector was also dropped and a whopping *4 newer major versions* are available from Apache since this answer was originally written. – Christopher Schultz Sep 22 '22 at 20:20
  • Good answer for cipher-order in general, but for BEAST as stated in the Q: both JSSE and OpenSSL (and also browsers) back in 2012 implemented 1/n or 0/n fragmentation as a _better_ fix to BEAST than RC4, and in subsequent years both TLSv1.0 and all RC4 suites (in any protocol) have become obsolete so that in 2022 both OpenSSL and JSSE, and nearly everything else too, reject both. – dave_thompson_085 Sep 23 '22 at 05:47
  • You’re right the fallback was removed with 8.5 already and the default was set to `false` (leave it to the client to decide which cipher to use) with introduction of the `SSLHostConfig` element. Thanks for clarification! – dpr Sep 23 '22 at 05:49
  • Yes, I have some familiarity with Tomcat 8.5. ;) – Christopher Schultz Sep 25 '22 at 19:54
1

During handshake the client sends the prefered cipher suites and the server chooses the strongest that both can support.
I am not sure what ordering you expect.

Also SSL Labs indicates that my site does not show a cipher preference, whereas google.com does

I can not understand what you mean here.
What exactly is the complaint? That from the enabled ciphers, Tomcat chose a less week than it supposed to?

user76678
  • 349
  • 3
  • 5
  • 16
  • Yes, the server picks the cipher. However, Tomcat is picking the cipher based on key strength only. I want to pick a non-CBC cipher first then the highest key strength. I mentioned the SSL Labs feedback as a note, not as a complaint. –  Sep 27 '11 at 20:11
  • I do not think that the preference is configurable (but I am not 100% sure).Here http://docs.huihoo.com/java/javase/7/technotes/guides/security/SunProviders.html#SunJSSEProvider it mentions the preference order by Java.I believe Tomcat uses that. BTW I still do not understand the SSLLabs feedback – user76678 Sep 27 '11 at 20:31
  • I did previously look at the [Java 6](http://download.oracle.com/javase/6/docs/technotes/guides/security/SunProviders.html#SunJSSEProvider) version of the link you gave, but it indicated the RC4 ciphers had priority (contrary to my results). Also, as you say, I could not find anything in any of the java docs I looked at about controlling the order. –  Sep 27 '11 at 21:26
  • I don't know how the SSL Labs site decides that a site has a cipher preference, but it indicated google had a preference for certain ciphers. Since it indicated my Tomcat site did not show a preference, it might indicate Tomcat or JSSE randomly chooses between ciphers of the same key strength, but I don't know for sure. I am beginning to think the way to figure this out is hunt down the source and maybe it is not worth the trouble. –  Sep 27 '11 at 21:26
  • Can you post the exact report of the SSL Labs for Google and your site?May be you are misunderstanding the report.I noticed that for Java 6 it mentions "table below shows the ciphersuites supported by SunJSSE in their default preference order".This seems to give a hint that perhaps the preference order could be changed but this statement was changed in 7 and the "default order was removed" – user76678 Sep 28 '11 at 06:42
  • @user967708 There is some misinformation here. There is nothing in JSSE or RFC 2246 that requires it to pick the strongest cipher. NB Tomcat doesn't pick the cipher, JSSE does, unless you are using the AJP connector with SSL, in which case OpenSSL does it. – user207421 Jul 12 '12 at 04:29
  • 1
    FWIW, SSLLabs can detect you have a cipher preference by sending a several client "hello" messages with different cipher orders specified and see which one the server chooses. If the server always chooses the first cipher the client offered, then the server does not have "a preference [for overriding the client's cipher preference]". – Christopher Schultz Nov 13 '14 at 19:14
1

I don't believe you can order them by preference and once you get rid of the CBC ones, there's an awfully short list of cipher options available! However, most clients are going to connect at RC4-128 any way--at least that's what all my server logs indicate when I feel like turning that logging option on.

Using the OpenSSL connector, you get the option of using a more concise syntax for allowing or disallowing certain ciphers but no options for setting cipher order or even preferred cipher.

mahnsc
  • 1,796
  • 13
  • 11