Securing SSL in Tomcat - Part One - SSLv2
Since the http connector in tomcat is very robust, stable, fast, etc., a lot of developers are opting to use tomcat as the front-end. I don't really recommend it because setting things up that the average developer does not set up can be a lot more difficult then setting it up on IIS and Apache. Controlling SSL behavior on tomcat is not all that well documented and can be extremely difficult to configure.
Ever since I started publishing trinkets and baubles on PCI compliance and remediation, I've seen a fair amount of referrals to this site where someone is looking to disable SSLv2 or weak ciphers on tomcat or jboss. The default http connector in tomcat contains a default attribute named "sslProtocol". On newer versions of tomcat the default setting for this attribute is "TLS"--even if you do not explicity define the attibute in the server.xml configuration. Interestingly, if you try to connect to your ssl-enabled tomcat site using SSLv2, you will fail. Try it out. You can validate it using cURL or the OpenSSL client. To validate in cURL, type the following at the command prompt:
./curl --verbose --sslv2 https://fqdn:[port]/
#[port] optional if 443 is standard for your site
You will see the following output:
* Unknown SSL protocol error in connection to :8443
* Closing connection #0
curl: (35) Unknown SSL protocol error in connection to :8443
If you want to give the ssl client in openssl a try, type the following at the command line:
./openssl s_client -ssl2 -connect :[port]
#[port] optional if 443 is the default
The connection attempt will fail with an error message similar to the following:
Loading 'screen' into random state - done
CONNECTED(00000108)
5312:error:1407F0E5:SSL routines:SSL2_WRITE:ssl handshake failure:.\ssl\s2_pkt.c
:428:
Swapping -ssl2
with -ssl3
or -tls1
will enable a successful connection.
On the server itself, start tomcat or jboss up with the -Djavax.net.debug=All
java option and you will get some very interesting ssl trace output. Clients connecting to the host over sslv2 result in the following output written to the tomcat/jboss server logs:
http-8443-1, setSoTimeout(60000) called
[Raw read]: length = 5
0000: 80 2E 01 00 02 .....
http-8443-1, handling exception: javax.net.ssl.SSLException: Unsupported SSL v2.
0 ClientHello
http-8443-1, SEND TLSv1 ALERT: fatal, description = unexpected_message
http-8443-1, WRITE: TLSv1 Alert, length = 2
[Raw write]: length = 7
0000: 15 03 01 00 02 02 0A .......
http-8443-1, called closeSocket()
http-8443-1, called close()
http-8443-1, called closeInternal(true)
From a PCI compliance standpoint, you should not be getting tagged with the site being vulnerable to SSLv2 but what you are probably getting tagged with are insecure ssl protocols and disabling them will be the subject of the second part of this series of posts. I've spent the past week testing this with tomcat 4.1.37, 5.5.27, and 6.0.18 with jdk1.4, jdk1.5, and jdk1.6 virtual machines and none of them allow an SSLv2 connection. If you are getting tagged with supporting SSLv2, you will probably need to update your JVM because newer JVMs don't even provide SSLv2 support.