Setting up the context:
In java 8 (precisely 8b98), in order to deal with Client-Initiated Renegotiation causing vulnerability to Denial of Service attack, an un-documented flag was rolled out named jdk.tls.rejectClientInitiatedRenegotiation as a part of Transport Layer Security which could disable client initiated renegotiations.
jdk.tls.rejectClientInitiatedRenegotiation = true
Server which i'm using is JBoss 7.1.1 which supports 7. However java 8 supporting servers are JBoss EAP & Wildfly. I'm reluctant to switch to these new server.
Now My challenge is to implement this property somehow in Java 7. Any sort of guidance will be highly appreciated.
Indeed Java 7 doesn't support this option. Maybe an acceptable behavior could be the Interoperable mode as in Description of Phase 2 Fix of the JSSE 7, which means enabling renegotiation for "good" clients ?
My exact answer is to switch to OpenSSL implementation, particularly the one with the hard-coded renegotiation denial, then you get rid of the JSSE implementation which doesn't support your hard-to-find option.
First, you need OpenSSL 0.9.8l which just denies all client renegotiations.
After that enable the Native Connectors on JBOSS 7.1 and configure as said in this documentation.
web archive links :
http://web.archive.org/web/20201019212829/https://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html
http://web.archive.org/web/20201027040002/https://www.openssl.org/news/secadv/20091111.txt
http://web.archive.org/web/20201123225554/https://docs.jboss.org/author/display/AS71/Admin%20Guide.html
Related
This question already has answers here:
Enable TLS 1.2 only in apache-tomcat-9 and Java 8
(3 answers)
Closed 1 year ago.
I'm new to tomcat. I've seen many links regarding changing the tls version in tomcat. All of them do one thing in common (ie) to configure the sslProtocol field in the below connector (in server.xml):
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLSv1.2" />
However I've changed this line to so many times to different versions. But whenever I test this using openssl, the server works only on TLSv1.2 and not any other versions. It seems that the field sslProtol in connector takes no effect on changing the TLS version. Is there anything that one needes to configure other than changing the version in the connector ? I've searched all over the web and stackoverflow and numerous answers. All seems to change the connector.
Is there anything other than configuring the connector to change the ssl/tls version like adding any external libraries or configuring the jdk or something like that .
Tomcat doesn't implemented SSL/TLS itself. Instead it relies on something external.
If you are using APR connectors, it uses on the OpenSSL engine installed on your platform.
If you are using BIO or NIO connectors, it uses the JSSE provider that your JVM is configured to use. That could either be the JSSE provider distributed as part of Java SE, or it could be a 3rd-party provider such as BounceCastle.
So ... if you can't get the "sslProtocol" parameter to actually select what you want, check that your JVM, JSSE provider or OpenSSL implementation actually supports the version you are trying to use.
Note that if you are using a "stack" that doesn't support (say) TLSv1.3, specifying that in the Connector config is not going to magically make it work. The SSL implementation code has to support it.
References:
How to find what SSL/TLS version is used in Java
Note that the above says what versions of SSL / TLS are supported by older versions of Java. It also provides some tips one figuring out what version is actually being used.
If you had told us clearly ...
what versions of SSL / TLS you were trying to use,
what Tomcat Connector class you were using, and
what versions of the respective software you were using ...
then I might have been able to give you more specific advice.
Recently I've been migrated to IBM MQ v8 to IBM MQ v9 (v9.1.2.0 specifically). I used SSL to communicate with the broker. So as per Deprecated CipherSpecs document, IBM has deprecated number of cipher suites that came up with MQ 8 and seems all of the cipher suites I've been using, have been deprecated with v9 upward. Therefore, I've implemented new TLS cipher suites to work with my application which runs on a Oracle JVM (version 1.8.0_211). Ever since I'm getting following exception in the application though;
com.ibm.mq.MQException: MQJE001: Completion Code '2', Reason '2400'.
at com.ibm.mq.MQManagedConnectionJ11.constructMQCD(MQManagedConnectionJ11.java:1437)
at com.ibm.mq.MQManagedConnectionJ11.constructCNO(MQManagedConnectionJ11.java:1537)
at com.ibm.mq.MQManagedConnectionJ11.<init>(MQManagedConnectionJ11.java:221)
... (Omitted the rest)
When I dig about the reason, found that's a problem with IBM MQ cipher suites and Oracle JRE cipher suite name mismatch. But I did refer TLS CipherSpecs and CipherSuites in IBM MQ classes for JMS document to map cipher suite names. I used some of Equivalent CipherSuite (Oracle JRE) column values in my application that already available in IBM MQ as well. But still getting the issue.
After I found this answer that advises to add this -Dcom.ibm.mq.cfg.useIBMCipherMappings=false argument to IBM MQ's JRE (As I understand). This might allow IBM MQ to use Oracle complied cipher suite names. My question is,
How to add this JVM argument -Dcom.ibm.mq.cfg.useIBMCipherMappings=false to IBM MQ JRE?
This Problem Connecting a Java Client (JMS) to a IBM MQ question suggests that the same parameter needed to be added to the application as a system property System.setProperty("com.ibm.mq.cfg.useIBMCipherMappings", "false"), but it didn't make any different.
Java connection to WMQ 8 question also states the same solution, but doesn't mention how to add this JVM argument to IBM MQ.
Update 1
I did some research about how to add a JVM argument to IBM MQ. But I was only able to find a solutions for Websphere application server.
CipherSuite I'm currently using in the application is;
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (Oracle JRE complied)
IBM MQ has respective;
ECDHE_ECDSA_AES_128_CBC_SHA256 (IBM MQ complied)
Update 2
After creating a key.kdb file with ikeyman tool with the stash option queue manager can successfully read the certificates in it. Also, I've included a self-signed certificate labeled with ibmwebspheremq<lowercase_queue_manage_name>. But now I'm getting a different exception in the client side;
Exception in thread "main" com.ibm.mq.MQException: MQJE001: Completion Code '2', Reason '2059'.
at com.ibm.mq.MQManagedConnectionJ11.<init>(MQManagedConnectionJ11.java:255)
at com.ibm.mq.MQClientManagedConnectionFactoryJ11._createManagedConnection(MQClientManagedConnectionFactoryJ11.java:450)
at com.ibm.mq.MQClientManagedConnectionFactoryJ11.createManagedConnection(MQClientManagedConnectionFactoryJ11.java:487)
at com.ibm.mq.StoredManagedConnection.<init>(StoredManagedConnection.java:97)
and in the MQ log I can find this entry;
AMQ9637E: Channel is lacking a certificate.
with some explanation.
After working for while, I was able resolve this issue. Since the beginning I had this certificate configuration issue in the application side. Even after creating self-signed certificate labeled after ibmwebspheremq<queue_manager_name> and shared the extracted certificates with the client application using ikeyman tool, AMQ9637E: Channel is lacking a certificate. occurred.
In a nutshell, to resolve this issue entirely, I did the following;
Update the client MQ dependency to com.ibm.mq.allclient:v9.1.2.0. If you're using maven, use following dependency (MQC91: IBM MQ Clients).
<dependency>
<groupId>com.ibm.mq</groupId>
<artifactId>com.ibm.mq.allclient</artifactId>
<version>9.1.2.0</version>
</dependency>
Now, if the application runs on an Oracle JVM, we should convince the MQ client lib to use Oracle JVM complied cipher suite names. To do that, either add this -Dcom.ibm.mq.cfg.useIBMCipherMappings=false as a JVM flag or add this System.setProperty("com.ibm.mq.cfg.useIBMCipherMappings", "false") as a system property.
Select a appropriate cipher suite to communicate with the MQ. This TLS CipherSpecs and CipherSuites in IBM MQ classes for JMS document would be helpful as IBM has deprecated number of weak cipher specs IBMMQ 9 onwards.
I would suggest to use ECDHE_* cipher specs as they provide Ephemeral Keys to maintain Forward Secrecy.
Then, using ikeyman GUI tool, I created a self-signed certificate labeled after ibmwebspheremq<queue_manager_name> name and instead of extracting the .arm file, I export the certificate as .jks files. Both keystore.jks and truststore.jks files exported from the same certificate. After, attached them to the application using system properties;
System.setProperty("javax.net.ssl.trustStore", "truststore.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "<password>");
System.setProperty("javax.net.ssl.keyStore", "keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "<password>");
With this configuration, SSL handshake issue went away, but the IBM MQ was still asking for user authentication with a user name and password. In order to provide them, should add these properties to MQEnvironment,
MQEnvironment.properties.put(com.ibm.mq.constants.CMQC.USER_ID_PROPERTY, "<user_name>");
MQEnvironment.properties.put(com.ibm.mq.constants.CMQC.PASSWORD_PROPERTY, "<password>");
These credentials were system credentials in my case.
If you simply want to skip user authentication like this, you can update IBMMQ config to skip credential check using runmqsc CLI tool like this (Refer this Turning on connection authentication on a queue manager document),
ALTER QMGR CONNAUTH(USE.PW)
DEFINE AUTHINFO(USE.PW) +
AUTHTYPE(IDPWOS) +
FAILDLAY(10) +
CHCKLOCL(OPTIONAL) +
CHCKCLNT(OPTIONAL)
REFRESH SECURITY TYPE(CONNAUTH)
Note that CHCKCLNT value needed to set as OPTIONAL to ignore client user credential check. IBM MQ should start to work with the client application whilst SSL enabled after these configurations.
Kudos to #JoshMc for the support to resolve this issue.
Note: Adding answer to capture information provided to OP in comments that have been removed.
See the following IBM MQ Knowledge center page for a table showing cert type compatibility with MQ v9.1:
IBM MQ 9.1.x/IBM MQ/Securing/Confidentiality of messages/Enabling CipherSpecs
The ciphers with ECDHE_ECDSA require a suite b cert for the queue manager. If using a client cert for your application it will also need to be suite b.
Note that you can use ECDHE_RSA ciphers with non-suite b certs.
The stash file (key.sth for example) is used by the queue manager to access the kdb file. The java equivalent on the client end is you specifying the jks password.
My java version is 1.6 and connect to a server over ssl using axis 2 stub; all used to work fine. It seems like they did some upgrade (apache2.4) and the ssl handshake doesn't happen anymore. I receive javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake error. Just for testing purpose, I locally installed jdk 8 and tested it works fine. Is there any way to make this work using jdk1.6? It is not possible to upgrade jdk now.
It is hard to tell without more details but I guess that the server either requires a TLS version unsupported by JDK 6 (e.g. TLS 1.1 or TLS 1.2) or uses ciphers which are not supported by JDK 6 yet. Another option might be that the server needs SNI (server name indication) which is not supported by JDK 6. If the problem is any of these things you are unfortunately out of luck with JDK 6.
I suggest you check with SSLLabs to get more details about the problem. They show also compatibility information regarding various JDK versions.
You could try using a 3rd party JCE provider, Bouncy Castle comes into mind:
https://www.bouncycastle.org
Because of the Poodle attack it is now recommended to disable SSLv3 for client and server applications and only allow TLS 1.0 -TLS 1.2 connections.
Is there a way to disable SSLv3 for all Java based applications (server and client) on a computer without having to modify every Java program?
May be there is a possibility to change the configuration of the JRE or using a special environment variable.
Does anybody know such a way?
You have not specified the version of Java because below Java 8 there is no way to disallow or disable specific SSL protocol but in Java 8 you can set the enabled protocols like following
Statically:
% java -Djdk.tls.client.protocols="TLSv1,TLSv1.1,TLSv1.2" MyApp
Dynamically:
java.lang.System.setProperty("jdk.tls.client.protocols", "TLSv1,TLSv1.1,TLSv1.2");
If you are still using java 7 or below try to use work around explained Instructions to disable SSL v3.0 in Oracle JDK and JRE
I just implemented following piece of code to disallow SSLv3 and SSLv2Hello on one of our Java6 application.
if(disabledSSLProtocols != null) {
String[] protocols = sslEngine.getEnabledProtocols();
List<String> protocolList = new ArrayList<String>();
for (String s : protocols) {
if (disabledSSLProtocols.contains(s)) {
log4j.info("{} protocol is disabled", s);
continue;
}
log4j.info("{} protocol is enabled", s);
protocolList.add(s);
}
sslEngine.setEnabledProtocols(protocolList.toArray(new String[0]));
}
Where disabledSSLProtocols initialized with SSLv3,SSLv2Hello
Take a look at http://www.oracle.com/technetwork/java/javase/overview/tlsreadme-141115.html
Relevant part:
Renegotiations can be re-enabled for those applications that need it by setting the new system property sun.security.ssl.allowUnsafeRenegotiation to true before the JSSE library is initialized. There are several ways to set this property:
Command Line:
% java -Dsun.security.ssl.allowUnsafeRenegotiation=true Main
Java Control Panel (Java Plug-in / Java Web Start) - Runtime Environment.
Within the application:
java.lang.System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", true);
Note that TLS/SSL renegotiation will not occur unless both client and server have enabled renegotiations.
It explains the issue and the fix.
For https-connections using the java.net-package you could try using the environment-variable _JAVA_OPTIONS to set the system-property https.protocols:
_JAVA_OPTIONS=-Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2
should enable only the mentioned protocols. Note that before Java 7 the maximum supported version was TLSv1.
This solution will not affect any other SSL-connections or http-connections using e.g. the apache-http-connector.
You can patch Oracle Java now.
http://www.oracle.com/technetwork/java/javase/documentation/cve-2014-3566-2342133.html
I was building an Active Directory Single Sign-On authentication system for Java web applications (using SPNEGO/Kerberos), and everything works fine with either Firefox or (reportedly) Safari, but Internet Explorer causes an exception:
GSSException: Channel binding mismatch (Mechanism level: ChannelBinding not provided!)
In fact, I thought IE worked before a Windows patch was installed.
Apparently, Microsoft IE patch KB974455 enabled "Extended Protection" for Integrated Windows Authentication. Normally, with SPNEGO/Kerberos authentication, the client machine acquires a Kerberos/Active Directory ticket for the server and presents this ticket during the HTTP authentication negotiation. As of at least Java 1.6, the Java JGSS-API library is capable of interpreting the SPNEGO/Kerberos negotiation and authenticating the ticket.
With the Extended Protection (see also Extended Protection for Authentication), IE adds a channel binding to the SPNEGO negotiation; what data the channel binding is based on is currently unknown to me, other than that the SSL session identifier seems to be part of it. The Java JGSS-API library attempts to validate the channel binding and canno without the data the binding is based on. It then throws the channel binding mismatch exception.
The issue has resulted in some internet traffic, including Sun Bug ID 6851973.
According to comments associated with 6851973, RFC 4121, says,
If the caller to GSS_Accept_sec_context [RFC2743] passes in
GSS_C_NO_CHANNEL_BINDINGS [RFC2744] as the channel bindings, then the
acceptor MAY ignore any channel bindings supplied by the initiator,
returning success even if the initiator did pass in channel bindings.
and "all major krb5 implementors implement this 'MAY'". JGSS appears to be requiring the acceptor to provide the channel binding if the initiator is presenting it. Further, the fix is available in Java 7, build 64 and will be back ported to Java 5 and 6, although the Java 6u18 does not appear to have it as reported in 6851973.
A work-around as seen in Extended Protection for Authentication is to set the
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA\SuppressExtendedProtection
registry setting to 0x02. This disables Extended Protection.