Transport Level Security (TLS) and Java

May 10, 2016 | 9 minute read
Text Size 100%:

Know Which Versions of TLS are Supported in Recent Java Versions

NOTE:  A more comprehensive examination of TLS and what to examine when setting up web service integrations in Oracle Cloud Saas extensions has been published.  See Transport Layer Security (TLS) and Web Service Connections in SaaS Integrations

In the twenty-plus years of the Internet’s interaction with the Secure Sockets Layer (SSL) and Transport Level Security (TLS) protocols, there have been some rough patches.  Over the years, various vulnerabilities, some of them exposed in a laboratory setting and others discovered and exploited by hackers, have made it necessary to revamp the protocols and to augment specifications.  Major changes to specifications, obviously, make it more difficult to support backwards compatibility, especially in a network as large and as decentralized as the Internet.  After all, it just isn’t realistic to declare by decree that every web site on the Internet upgrade its older, insecure version of SSL or TLS in favor of the new and improved security framework du jour.

Another problem, somewhat related to backwards compatibility, is that the Internet, due to its sheer size and diversity, cannot react instantaneously to an upgraded security protocol, and that the client agents and programming languages need time to assimilate security protocol changes into their own upgrade and version release schedules.  A major case in point is the Java language, which is perhaps the most widely used programming language for developing applications that are designed to communicate with clients and/or with other servers over both private and public networks.  Occasionally, special handling in some versions of Java is required to allow applications to communicate with each other using the latest and greatest versions of these security protocols.  Working with these Java versions as needed given certain versions of TLS is covered here.

A Little History:  SSL Under Siege

In the Internet’s formative years, when it was still the exclusive domain of scientific researchers and developers, before commerce and entertainment became Internet channels, and before it became a part of everyday life and business for millions, few users would have put a very high priority on the need to add a security layer to communications, even though it was a public network.  Of course, priorities changed quickly as the Internet’s usage patterns expanded, as more and more people started using the Internet for more and more things.  With increased popular usage, and with the expanded potential for usage in commerce, the incentive for hijacking network communications became more lucrative potentially.  It became obvious that if the Internet were to take on an expanded role, and if privacy was going to be respected, something would have to be done to protect sensitive data transmissions from unauthorized snoopers and others with criminal intentions.

And thus the Secure Sockets Layer, or SSL, protocol was born.  The original authors and developers of the specification identified three core functional areas:

  • Privacy: Use of encryption
  • Identity authentication: System Identification using certificates
  • Reliability: Maintaining a secure connection with message integrity checking

Attempts to implement these features securely in the first few major versions of the SSL protocol went down a path fraught with false starts and wrong turns.  Indeed, SSL version 1.0, developed by Netscape in the early 1990’s, was never even released publicly due to a large number of security flaws.  (There are claims that SSL v1.0 was cracked ten minutes after Netscape introduced it to the developer community.)  SSL v2.0, released in 1995, also had numerous security gaps, which forced a ground-up redesign and rework of the protocol.  This work culminated in the release of SSL v3.0 in 1996 (IETF RFC 6101).

Up until version 3.0 of SSL, drafting the specifications and doing the actual work largely fell under the purview of one vendor, Netscape.  Technically speaking, therefore, the first few versions of the protocol were proprietary solutions.  Due to security’s increasing significance and importance the IETF governing body took over management of SSL after version 3.0 was released.  Renaming SSL to Transport Level Security (TLS) was one of the body’s first actions, and after that there were a number of incremental revisions to TLS, resulting in TLS 1.0, 1.1, and TLS 1.2, which is the most recent iteration of the specification and protocol.

Historically, vulnerabilities tended to cluster around two key components of the SSL/TLS protocols:  exploiting holes in the initial handshake process, or finding gaps in either the encryption process or the encrypted data.  In SSL v2.0, for example, one of the early exploits manipulated the list of available cipher suites presented to a communications partner during the handshake process, thereby forcing a weaker cipher, smoothing the way for Man-In-The-Middle attacks to be successful.  SSL v3.0 filled this hole, along with incorporating other improvements, but vulnerabilities continued to be uncovered, resulting eventually in TLS 1.0.  Despite improvements in TLS over SSL, this family of cipher suite downgrade attacks continues to be relevant for even newer versions of TLS.

Researchers have been (and continue to be) major contributors in identifying weaknesses and security holes in SSL and TLS.  The BEAST, CRIME, and BREACH attacks were identified in 2011 and 2012, resulting in a number of supplied fixes from browser and O/S vendors.  Some browsers were more open to these types of attacks than others.

Even after fixes and improvements were incorporated into TLS 1.0, Google Security Team researchers were able to uncover a means of accomplishing a Man-In-The-Middle exploit by taking advantage of TLS 1.0’s built-in behavior of reverting back to SSL 3.0 to support backwards compatibility for communications partners.  Exposed in late 2014, this came to be known as the POODLE vulnerability, and it set off a flurry of corrective activity from browser vendors and language providers alike.  The net result was a wholesale movement to remove support for SSL 3.0 in browsers and networked applications.

In addition to the defects uncovered in the various SSL and TLS specifications, bugs in library implementations have also been problematic for secure network communications.  In early 2014, the Heartbleed bug/vulnerability in the extremely popular OpenSSL software stack opened up websites to the potential for compromising their secret private keys, thereby making it possible for attackers to eavesdrop on communications, impersonate identities, and steal valuable data.

SSL/TLS and Java Support

This brief historical overview of SSL and TLS demonstrates that the protocol specifications have been extremely fluid and have never been in a state that other technologies can just take as a constant.  The protocols are in many ways moving targets that other computing technologies, such as Java, need to take into account when patches and major upgrades are released.  There have been occasions when TLS has incorporated a fix for an identified security gap (take the somewhat recent POODLE exploit as an example), and other technologies that interact with SSL/TLS have little choice but to “catch up” in their support of the new additions.  This is especially true when the solution involves removing support for an older protocol, such as what happened with POODLE and SSL 3.0.  The time lags are unfortunate, but due to the “late-breaking” nature of security holes when they are discovered, there does not seem to be much of an alternative.

Over time, Java releases have reacted to the evolution of SSL and TLS by building in support for newer releases of the security protocols.

Java Version SSL/TLS Default Other Supported Versions
Java 6 TLS 1.0 TLS 1.1 (update 111 and later), SSLv3.0*
Java 7 TLS 1.0 TLS 1.2, TLS 1.1, SSLv3.0*
Java 8 TLS 1.2 TLS 1.1, TLS 1.0, SSLv3.0*

* SSLv3 support disabled in January, 2015 patch releases

Up until January, 2015, all of the above-listed Java releases had fallback support for SSL 3.0.  As a response to the late-2014 POODLE exploit, Oracle issued CPU releases in early 2015 (JDK 8u31, JDK 7u75, and JDK 6u91), to disable SSL v3 by default.  Publicly available Java 6 releases do not have built-in support for TLS 1.2.  Java 8, with its default support for TLS 1.2, has caught up with the latest released specification of the protocol.

Due to POODLE, the vast majority of web sites have disabled support for SSL 3.0 on their servers.  There has been related momentum building up in the Internet security community to recommend disabling “early” versions of TLS as well, as there are known security issues both in TLS 1.0 and TLS 1.1.  Running only TLS 1.2, however, may block older browsers and other clients from connecting successfully.  This represents a tradeoff between tightly clamping down on security versus being a bit more flexible about supporting older browsers and other clients.

Clients (and servers connecting to other servers as clients) dependent upon the Java 7 JDK and JRE may be affected negatively by sites allowing only newer TLS versions.  By default Java 7 does not successfully negotiate with TLS 1.1 and TLS 1.2 servers.  If attempts to connect with a Java 7 client result in a stacktrace with an SSLHandshakeException it is possible that the default client behavior will need to be modified.  The expanded stacktrace (taken from a SOAPUI session) makes it fairly clear that the server is shutting down the client connection before the handshake sequence can complete:

javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
        at sun.security.ssl.SSLSocketImpl.checkEOF(Unknown Source)
        at sun.security.ssl.SSLSocketImpl.checkWrite(Unknown Source)
        at sun.security.ssl.AppOutputStream.write(Unknown Source)
        at org.apache.http.impl.io.AbstractSessionOutputBuffer.flushBuffer(AbstractSessionOutputBuffer.java:131)
        at org.apache.http.impl.io.AbstractSessionOutputBuffer.flush(AbstractSessionOutputBuffer.java:138)
        at org.apache.http.impl.conn.LoggingSessionOutputBuffer.flush(LoggingSessionOutputBuffer.java:95)
        at org.apache.http.impl.AbstractHttpClientConnection.doFlush(AbstractHttpClientConnection.java:270)
        at org.apache.http.impl.SocketHttpClientConnection.close(SocketHttpClientConnection.java:245)
        at org.apache.http.impl.conn.DefaultClientConnection.close(DefaultClientConnection.java:164)
        at org.apache.http.impl.conn.AbstractPooledConnAdapter.close(AbstractPooledConnAdapter.java:152)
        at org.apache.http.protocol.HttpRequestExecutor.closeConnection(HttpRequestExecutor.java:142)
        at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:129)
        at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:633)
        at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:454)
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754)
        at com.eviware.soapui.impl.wsdl.support.http.HttpClientSupport$Helper.execute(HttpClientSupport.java:233)
        at com.eviware.soapui.impl.wsdl.support.http.HttpClientSupport.execute(HttpClientSupport.java:323)
        at com.eviware.soapui.impl.wsdl.submit.transports.http.HttpClientRequestTransport.submitRequest(HttpClientRequestTransport.java:290)
        at com.eviware.soapui.impl.wsdl.submit.transports.http.HttpClientRequestTransport.sendRequest(HttpClientRequestTransport.java:220)
        at com.eviware.soapui.impl.wsdl.WsdlSubmit.run(WsdlSubmit.java:119)
        at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
        at java.util.concurrent.FutureTask.run(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)
Caused by: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
        at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
        at sun.security.ssl.SSLSocketImpl.writeRecord(Unknown Source)
        at sun.security.ssl.AppOutputStream.write(Unknown Source)
        at org.apache.http.impl.io.AbstractSessionOutputBuffer.flushBuffer(AbstractSessionOutputBuffer.java:131)
        at org.apache.http.impl.io.AbstractSessionOutputBuffer.write(AbstractSessionOutputBuffer.java:151)
        at org.apache.http.impl.conn.LoggingSessionOutputBuffer.write(LoggingSessionOutputBuffer.java:74)
        at org.apache.http.impl.io.ContentLengthOutputStream.write(ContentLengthOutputStream.java:114)
        at org.apache.http.impl.io.ContentLengthOutputStream.write(ContentLengthOutputStream.java:120)
        at org.apache.http.entity.ByteArrayEntity.writeTo(ByteArrayEntity.java:68)
        at org.apache.http.entity.HttpEntityWrapper.writeTo(HttpEntityWrapper.java:96)
        at org.apache.http.impl.client.EntityEnclosingRequestWrapper$EntityWrapper.writeTo(EntityEnclosingRequestWrapper.java:108)
        at org.apache.http.impl.entity.EntitySerializer.serialize(EntitySerializer.java:120)
        at org.apache.http.impl.AbstractHttpClientConnection.sendRequestEntity(AbstractHttpClientConnection.java:263)
        at org.apache.http.impl.conn.AbstractClientConnAdapter.sendRequestEntity(AbstractClientConnAdapter.java:227)
        at org.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:255)
        at com.eviware.soapui.impl.wsdl.support.http.HttpClientSupport$SoapUIHttpRequestExecutor.doSendRequest(HttpClientSupport.java:119)
        at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:123)
        ... 14 more
Caused by: java.io.EOFException: SSL peer shut down incorrectly
        at sun.security.ssl.InputRecord.read(Unknown Source)
        ... 32 more

SSL handshake failures typically occur because the client and the server cannot agree on which version of the protocol to use.  In the case of a default Java 7 client and a server that supports TLSv1.2 and possibly TLSv1.1, there is no common ground for agreement because there are no shared, supported protocols.  At the beginning of the handshake process, the Java 7 client sends a "ClientHello" message with an indication that it is ready to support the TLSv1 protocol (or anything older such as SSLv3.0).  The server sees the request but has no choice other than to close the connection because it knows the client cannot support TLSv1.2 or TLSv1.1.

To work around this issue, supply the command line directive “-Dhttps.protocols=TLSv1.2,TLSv1.1,TLSv1” when starting the Java VM, or in code, the equivalent system property directive is “System.setProperty(“https.protocols”, “TLSv1.2,TLSv1.1,TLSv1”)".  If connecting to a TLS 1.1 or TLS 1.2 site from a JEE server environment, it will be necessary to add the command line directive to the server’s startup scripts.  With Weblogic, for example, editing the Java startup properties in the setDomainEnv.sh script should get the job done.  (NOTE:  Modifying the Java startup properties in this manner addresses the handshake process only.  For extending Java support of SSL-related cryptography libraries in Weblogic, which may be necessary to support newer certificate standards, see Olaf Heimburger's blog, Improve SSL Support for Your Weblogic Domains .)

With these directives in place the handshake process succeeds.  Initially, the Java 7 client sends a "ClientHello" message, but now it indicates that it can support the TLSv1.2 protocol.  The server responds, certificate information is sent, a cipher suite is agreed upon, and protected communications between the two parties can begin.

To determine with certainty which version(s) of the TLS protocol are supported by a target web site, Qualys SSL Labs provides a free online service (https://www.ssllabs.com) that provides audit reports of SSL URL endpoints.  In addition to certificate details, supported cipher suite listings, and simulated handshake sequences with a variety of user agents (including Java 6, Java 7, and Java 8), the report has a section on enabled protocols for the site.

Not so coincidentally, repeated unsuccessful attempts to connect to a security-upgraded web site with a default Java 7 client was the catalyst for this research and writeup.  Here is the supported protocol summary from the SSL Labs online report for the problematic (at least for Java 7 configured with the defaults) site:

SSLLabsProtocols

Many endpoints protected by SSL/TLS are serving SOAP or REST web services.  The current release of Smart Bear Software’s popular testing tool, SOAPUI, is built with Java 7, so it too will need special configuration when trying to connect to a TLS 1.1 or TLS 1.2 SOAP or REST endpoint.  One may think that setup for a successful handshake with the server would be to add the Java command line directive detailed above in the SOAPUI startup sequence.  Although seemingly a sound strategy, this does not lead to success; SOAPUI has put in place its own command line configuration modifiers.  Adding “-Dsoapui.https.protocols=TLSv1.2,TLSv1.1,TLSv1.0” to the JAVA_OPTS environment variable in the soapui.bat file will work successfully, however.

Looking Ahead

With default support in Java 8 for TLS 1.2, the current release of the security protocol, it makes the most sense to run Java client applications with Java 8 if there is some flexibility in being able to choose the Java version.  Without that flexibility, If running Java 7 is the only option, then it will be necessary to modify Java startup parameters for the application if the communications target has both SSLv3 and TLSv1.0 disabled.  This non-default setup requirement may become more and more a necessity as more and more secure endpoints disable TLS1.0 along with SSLv3.0.  But at the same time, applications should slowly but surely start to uptake Java 8, so the non-default configuration settings requirement for Java 7 should be short-lived.

Additional Resources

The following on-line resources were helpful in compiling this document:

Java SE 7 Security Enhancements Documentation:  http://docs.oracle.com/javase/7/docs/technotes/guides/security/enhancements-7.html

Java SE 8 Security Enhancements Documentation:  https://docs.oracle.com/javase/8/docs/technotes/guides/security/enhancements-8.html

Java Platform Group Blog: Diagnosing TLS, SSL, and HTTPS : https://blogs.oracle.com/java-platform-group/entry/diagnosing_tls_ssl_and_https

 

Bill Jacobs


Previous Post

Creating a Mobile-Optimized REST API Using Oracle Mobile Cloud Service - Part 4

Steven Davelaar | 8 min read

Next Post


BPM 11g to 12c Upgrade Notes

John Featherly | 3 min read