How do I disallow particular SSL protocols in Jett

2019-04-10 20:45发布

问题:

I have a web application running on Jetty 6 + Open JDK 7 on Debian 6.0.7. I have a security requirement to accept a TLS handshake but not an SSLv3.0 handshake when a client initiates an HTTPS connection.

In my jetty.xml I set the protocol to TLS:

<New class="org.mortbay.jetty.security.SslSocketConnector">
    <Set name="protocol">TLS</Set>
    ...

With this configuration, the web server still appears to accept an SSLv3.0 handshake. This has been verified with the 'sslscan' tool and running 'curl -sslv3 -kv {host}'.

Is it possible to configure Jetty to only accept a TLS handshake? I would be willing to upgrade my Jetty version if needed.

回答1:

I found two solutions:

Upgrade to Jetty 9, which supports the jetty.xml entry:

<Arg name="sslContextFactory">
    ...
    <Set name="excludeProtocols">
      <Array type="java.lang.String">
        <Item>SSLv3</Item>
      </Array>
     </Set>

Or, with Jetty 6 create delegate classes for SslSocketConnector and SSLServerSocketFactory:

jetty.xml:
  ...
  <New class="com.src.TlsSocketConnector">
    ...
  </New>

public class TlsSocketConnector extends SslSocketConnector  {
  @Override
  protected SSLServerSocketFactory createFactory() throws Exception {
    return new TlsServerSocketFactory( super.createFactory() );
  }
}

public class TlsServerSocketFactory extends SSLServerSocketFactory {

  private SSLServerSocketFactory delegate;

  public TlsServerSocketFactory( SSLServerSocketFactory delegate ) {
    this.delegate = delegate;
  }

  //Repeat this pattern for all createServerSocket() methods
  public ServerSocket createServerSocket() throws IOException {
    SSLServerSocket socket = (SSLServerSocket) delegate.createServerSocket();
    socket.setEnabledProtocols( new String[]{"TLSv1", "TLSv1.1", "TLSv1.2"});
    return socket;
  }

  // Directly delegated methods from SSLServerSocketFactory
  public String[] getDefaultCipherSuites() { return delegate.getDefaultCipherSuites(); }
  public String[] getSupportedCipherSuites() { return delegate.getSupportedCipherSuites(); }
}


回答2:

For Jetty 6, you could also create an overridden SslSelectChannelConnector that removes SSLv3, like this:

package com.mycompany;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import javax.net.ssl.SSLEngine;

import org.mortbay.jetty.security.SslSelectChannelConnector;

public class SslSelectChannelConnectorNoSsl3 extends SslSelectChannelConnector {

  @Override
  protected SSLEngine createSSLEngine() throws IOException {
    SSLEngine engine = super.createSSLEngine();
    Set<String> protocols = new HashSet<String>(Arrays.asList(engine.getEnabledProtocols()));
    protocols.removeAll(Arrays.asList("SSLv2Hello","SSLv3"));
    engine.setEnabledProtocols(protocols.toArray(new String[protocols.size()]));
    return engine;
  }

}

And then specify that connector in jetty.xml, like this:

<Call name="addConnector">
 <Arg>
   <New class="com.mycompany.SslSelectChannelConnectorNoSsl3">
   ...
   </New>
 </Arg>
</Call>