Question

We run a web application on Tomcat 6 using the native Apache Portable Runtime SSL connector to provide SSL connectivity. How can we configure the server to prevent against the BEAST attack?. The suggested solution (1) can not be configured in the Tomcat configuration, because it does not allow to set the SSLHonorCipherOrder parameter (2).

We currently use only the setting SSLCipherSuite="ECDHE-RSA-AES256-SHA384:AES256-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM" but a scan using the SSL Server Test shows the server is still vulnerable against the BEAST attack. I know we can solve the issue by fronting Tomcat with an Apache proxy, but this change is too invasive to implement in the short term. I can also patch Tomcat to add support, but this would prevent automatic updates of the Tomcat package which goes against policies.

1: https://community.qualys.com/blogs/securitylabs/2011/10/17/mitigating-the-beast-attack-on-tls

2: http://tomcat.apache.org/tomcat-6.0-doc/apr.html

Était-ce utile?

La solution 2

I never posted my solution this. It is a bit of a hack, but you do not need to patch/recompile either JSSE or Tomcat.

Create the following class:

/*
SSLSettingHelper prevents BEAST SSL attack by setting the appropriate option.
Due to protected variable must be in org.apache.tomcat.util.net package...
Instruction:
1) Compile and place JAR in tomcat /lib
2) Add protocol="org.apache.tomcat.util.net.SSLSettingHelper" to SSL APR connector
*/
package org.apache.tomcat.util.net;

public class SSLSettingHelper extends org.apache.coyote.http11.Http11AprProtocol {
    @Override
    public void init() throws Exception {
        super.init();
        org.apache.tomcat.jni.SSLContext.setOptions(endpoint.sslContext, org.apache.tomcat.jni.SSL.SSL_OP_CIPHER_SERVER_PREFERENCE);
        log.info("SSLSettingHelper set SSL_OP_CIPHER_SERVER_PREFERENCE to prevent BEAST SSL attack");
    }
}

Then configure the connector to using this helper class:

<Connector server="Server" protocol="org.apache.tomcat.util.net.SSLSettingHelper" port="8443" maxThreads="256" scheme="https" secure="true" SSLEnabled="true" SSLCertificateFile="..." SSLCertificateKeyFile="..." SSLCertificateChainFile="..." SSLCipherSuite="ECDHE-RSA-AES256-SHA384:AES256-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM" compression="on" compressableMimeType="text/html,text/xml,text/plain,application/json,text/css,text/javascript" maxPostSize="1024000"/>

This fixes the BEAST attack.

Autres conseils

The logical way to solve this problem is for Tomcat to implement a CipherOrder directive, which as this BugZilla link shows, seems to be incorporated in Tomcat 7.0.30 onwards. I am most interested to try this out, will feedback after trying. https://issues.apache.org/bugzilla/show_bug.cgi?id=53481

I found an solution to enable in plain java the same like "SSLHonorCipherOrder". Patching some lines the orig Sun JSSE via (bootclasspath) to get Server Server order working.

Class: sun.security.ssl.ServerHandshaker

Add Field

public static boolean preferServerOrder = true;

Replace Method chooseCipherSuite:

private void chooseCipherSuite(final HandshakeMessage.ClientHello mesg) throws IOException {
    if(preferServerOrder) {
        final CipherSuiteList clientList = mesg.getCipherSuites();
        for(final CipherSuite serverSuite : getActiveCipherSuites().collection()) {
            if (this.doClientAuth == 2) {
                if (serverSuite.keyExchange == CipherSuite.KeyExchange.K_DH_ANON) continue;
                if (serverSuite.keyExchange == CipherSuite.KeyExchange.K_ECDH_ANON) continue;
            }
            if(!serverSuite.isNegotiable()) continue;
            if(clientList.contains(serverSuite)) {
                if (trySetCipherSuite(serverSuite)) return;
            }
        }
    } else {
        final Collection list = mesg.getCipherSuites().collection();
        for(final CipherSuite suite : list) {
            if (!(isNegotiable(suite))) continue;
            if (this.doClientAuth == 2) {
                if (suite.keyExchange == CipherSuite.KeyExchange.K_DH_ANON) continue;
                if (suite.keyExchange == CipherSuite.KeyExchange.K_ECDH_ANON) continue;
            }
            if (trySetCipherSuite(suite)) return;
        }
    }
    fatalSE(Alerts.alert_handshake_failure, "no cipher suites in common");
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top