How to reactivate TLS1.0 in JRE8u60 - java

We have a Java desktop product that our customers (small businesses) use (among other things) to communicate with larger insurers via a few different SOAP protocols. (We are the SOAP client). The point here is that the insurers are the gorillas in the room - we just enable the communication between the insurers and our customers.
We use AXIS1 as our SOAP client library. Ordinarily is works perfectly and it has for years.
One major insurer is still using TLS1.0 for their SOAP server. We have no influence over this any more than the international space station affects the orbit of the earth.
Unfortunately (for us) the latest Java version 8u60 automatically disables TLS1.0.
see JDK-8076221 : Disable RC4 cipher suites
at http://bugs.java.com/view_bug.do?bug_id=8076221
So now we have customers who cannot connect via 8u60. We can revert them to 8u51, but that is short term at best.
JDK-8076221 gives a few clues on how to re-enable TLS1.0 as follows ...
These cipher suites can be reactivated by removing "RC4" form
"jdk.tls.disabledAlgorithms" security property in the java.security
file or by dynamically calling Security.setProperty(), and also
readding them to the enabled ciphersuite list using the
SSLSocket/SSLEngine.setEnabledCipherSuites() methods.
Unfortunately for someone like me (who has relied on the security layer being abstracted away) this is not enough information.
Comments
TLS level control is not my thing - we have relied on AXIS etc to do
all of that behind the scenes so there is a large body of knowledge
that is not familiar to me.
We have no control on the insurer using a TLS1.0 interface.
If we don't get a work around here our customers will simply be forced to use other products
that will use TLS1.0 - so we can't play hard ball and save anyone
here. They will be using TLS1.0 until the insurer decides otherwise.
A dynamic (code based) solution is preferred to any command line solution because we are a desktop application that will find command line deployment extremely problematic.
Can anyone provide some more detailed clues on how to programatically enable TLS1.0 in Java 8u60?
Perhaps something like ...
Security.setProperty("jdk.tls.disabledAlgorithms", "SSLv3");
SSLContext sslCtx = SSLContext.getInstance("TLS");
SSLSocket.setEnabledCipherSuites("please help me!");
SSLEngine.setEnabledCipherSuites("please help me!");
Many thanks for your time,
-Damian

Check http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html for algorithm names.
TLS 1.0 is matched by "TLSv1" (section SSLContext Algorithms), hence something similar to the following will enable TLS 1.0 (note that this applies for the instance of SSLEngine returned by createEngine()).
SSLContext.getDefault().createSSLEngine().setEnabledCipherSuites(new String[] {"TLSv1"});
For enabling a cipher suite you must overwrite the current value with something differently. You code disables SSLv3 which is already disabled. Instead you would need something similar to
Security.setProperty("jdk.tls.disabledAlgorithms", "");
However before doing that check how these properties actually work. It would expect the Security property to contain the names of ciphersuites for example as comma separated list. So you should do something like
String disabledAlgorithms = Security.getProperty("jdk.tls.disabledAlgorithms");
Security.setProperty("jdk.tls.disabledAlgorithms", disabledAlgorithms .replace("RC4,", ""));

Related

Would having a constant KeyStore make this any less secure?

I'm writing a bit of a net utility, and I want it to have three protocols. PLAIN_TEXT, which, obviously, sends plain text/bytes over the network. ENCRYPTED_UNSECURED, which uses encryption, but doesn't verify any identities, and ENCRYPTED_SECURED, which uses SSL or TSL.
Right now, I've implemented PLAIN_TEXT, and I've partially implemented ENCRYPTED_UNSECURED, but I've hit a block. I'm using SSLSockets for ENCRYPTED_UNSECURED, but with self-signed certs and a fake trust manager, however, the self-signed certs need to come from a key manager, which comes from a keyfile, generated by the java key tool.
What I want to know is: would using the same key file in every instance of the server/client subtract from the security of the encryption? As it is ENCRYPTED_UNSECURED, I don't care about the security of the authentication.
Note: this is being done in java.
EDIT: Why this is not a duplicate?
I'm not trying to import the certificate, I know how to do that, I want to know if using the same certificate could decrease the security of SSL/TSL's encryption protocol.
First, don't use actual SSL; SSLv2 was broken long ago (before 2000), and SSLv3 is now broken in most situations by POODLE (see Wikipedia and/or about a dozen questions on security.SE and crypto.SE). (Note the pseudoprotocol SSLv2Hello in Java/JSSE is not actually SSLv2 and is not a security vulnerability; OTOH since maybe 2010 it is very rarely needed or useful and nowadays more likely to cause confusion.)
Caveat: Java uses an "architecture" for cryptography that allows the same function(s) to be performed by different "providers" depending on how (by whom) your JRE is built and whether your installation has been modified. I will assume you use an Oracle (or formerly Sun) version of Java, or another version that uses the same cryptoproviders, which may include OpenJDK (which is mostly the same source as Oracle/Sun). In particular #Michal's answer seems to assume IBM although I see nothing in your question indicating this; IBM Java although otherwise compatible with Oracle/Sun Java has its own set of cryptoproviders and I don't know if any of the IBM differences affect the issues here.
Finally(!) to your question: distributing one privatekey (keystore) to numerous parties increases the risk of compromise at least proportionally to the number -- perhaps more because people are usually less careful about things that they perceive as someone else's responsibility.
TLS (like SSL before it) supports several different keyexchange options.
Ephemeral Diffie-Hellman in either classic (Zp) form DHE or elliptic-curve form ECDHE. These are usually preferred, and in particular Java/JSSE client orders them first (except for bugs on some early updates of Java7) because they provide Perfect Forward Secrecy; treating now as the beginning of the future -- as the saying goes 'today is the first day of the rest of your life' -- this also preserves confidentiality even if the server privatekey is already compromised, at least assuming the DHE/ECDHE implementation is correct.
Be sure not to use (Zp) DHE if the server runs on Java7 or earlier; those versions used 768-bit DH group which is too small. Java8 defaults to 1024, which is enough except perhaps against top adversaries like NSA, see details at http://weakdh.org; and can be configured for 2048 which is definitely enough, see
How to expand DH key size to 2048 in java 8
or several others. Note Java7 and up (but not 6 out of the box) support both DHE and ECDHE and prefer ECDHE, and Java ECDHE uses adequate curves, so in practice this should not be a problem.
(Plain) RSA. This is not secure if the privatekey is compromised, so in your situation you should if at all possible disable all plain-RSA ciphersuites. Ciphersuites of the form {TLS,SSL}_DHE_RSA_.. and TLS_ECDHE_RSA_... use RSA only for authentication not encryption; it is {SSL,TLS}_RSA_... that you must avoid.
Anonymous. TLS also supports keyexchange with DH or ECDH ephemeral keys but NO AUTHENTICATION (i.e. no certificate at all); these suites are called 'anonymous' instead of ephemeral and have the form {SSL/TLS}_{DH,ECDH}_anon_.... This is actually the exact technical match to your goal of providing confidentiality but not authentication, and needs NO keystore on the server or truststore on the client, plus avoids the hostname issue below. The possible downside is that anonymous suites are disabled by default, precisely because most users expect 'Secure Sockets' or 'Transport Security' to be secure, so you must enable them (at both ends); also if your organization (or your user's if different) has actually thought about a security policy, that thinking fairly often prohibits anonymous TLS for the same reason, and unlike some policy items this one can almost always be enforced by scans or monitors.
Others. TLS also supports nonephemeral aka static DH and ECDH, but practically no one uses them. TLS also supports non-PKC schemes using Kerberos, SRP, or just an arbitrary key (PSK), but these generally are appropriate only in special situations. Of these Java supports static-ECDH and Kerberos; using static-ECDH in your situation would be as insecure as plain-RSA, and IME even in environments where Kerberos is available using it with Java is about as much fun as hitting yourself in the head with hammers.
Hostname check: finally, for (non-anonymous) suites using a certificate, Java SSL/TLS client normally checks that the name used to connect to the server (either a domainname or an IP address) matches the certificate; the certificate must contain either
the name/address of the server, of which there can be more than one using SubjectAltNames aka SAN extension which is supported by keytool beginning in Java7 -- but a full list of names is difficult to arrange if you are going to use one cert on many servers especially ones you didn't identify in advance;
or a name with a 'wildcard' in the first component only: i.e. *.fred.example.com can be used for test1.fred.example.com test9999.fred.example.com anything.fred.example.com but NOT test.john.example.com anything.example.net or even fred.example.com (one level higher).
This check can be overridden, although the details vary some depending on whether you are using HTTPS or not and the Java version. Using anonymous suite(s) as above avoids the issue entirely.

Java-6 to Java-7 Kerberos - breaking behaviour change sessionKey now AP-REQ.Authenticator.subkey

I'm working on a project where we use JAAS/Krb5LoginModule with useTicketCache & doNotPrompt as well as the allowtgtsessionkey registry change to piggy back our authentication on the windows logon of the domain joined computer.
We then use jgss/kerberos to get a GSS API Kerberos Token (rfc1964) which we use to secure a SOAP Message using the WSS Kerberos Token Profile 1.1.1 when communicating with a service. This involves including the b64 encoded GSS Token in the Security element of the SOAP Envelope/Header and using the client/service sessionKey to sign a component of the element.
We are getting the client/sessionKey by querying the private credentials of the javax.security.auth.Subject which the JAAS/Krb5LoginModule returns and looking for a javax.security.auth.kerberos.KerberosTicket which matches our service peer name and invoking its getSessionKey().
All of this works fine in Java-6, however Java-7 clients are failing as there seems to have been a change in the Kerberos KRB_AP_REQ message that Java-7 creates. The Java-7 KRB_AP_REQ Authenticator contains a sub-key which is different to the sessionKey. Since the Kerberos specification (see excerpt below) says that this subkey supersedes the sessionKey then our Java-6 behaviour of using the sessionKey for signing is no longer correct.
RFC1510 - The Kerberos Network Authentication Service (V5)
5.3.2. Authenticators
subkey This field contains the client's choice for an encryption
key which is to be used to protect this specific
application session. Unless an application specifies
otherwise, if this field is left out the session key from
the ticket will be used.
I've not seen anywhere where this change is documented but have confirmed the behaviour at least in Java(TM) SE Runtime Environment (build 1.7.0_11-b21).
At this point unless I have missed something glaringly obvious (and I hope I have), our options seem to be:
Change the Java-7 Kerberos Configuration to revert to Java-6 behaviour - unfortunately I've not seen anything in the docs that seems to suggest that this is possible.
Find a way to get access to the subkey. For this options I have explored are
a. Decode the b64 encoded GSS Token, pull out the encrypted Authenticator, decrypt it using the sessionKey, decode the ASN.1 DER encoding and pull out the subkey.
b. Use what appears to be non-standard GSS API Extensions and use the ExtendedGSSContext.inquireSecContext() method with KRB5_GET_SESSION_KEY to get at the subKey.
Any suggestions/insight in to these or other possible options?
We also experience this issue when using JGSS Api in Java 1.7 to obtain the client's session key. Apparently, in Java 1.6 the sub-key was always cloned from the session key, see the sun.security.krb5.EncryptionKey constructor:
EncryptionKey(EncryptionKey encryptionkey)
throws KrbCryptoException
{
keyValue = (byte[])(byte[])encryptionkey.keyValue.clone();
keyType = encryptionkey.keyType;
}
Starting from Java 1.7.0_b07, this constructor utilizes java.security.SecureRandom to generate a new subkey. I think this has been done as part of JDK-4460771 : Kerberos should be able to generate sub-session keys. It seems that the com.sun.security.jgss.ExtendedGSSContext provides the "standard" way to access the subkey from now on (on Sun JVMs), so I guess we should use this class if it is available (on the underlying JVM), see:
JDK-6710360 : export Kerberos session key to applications
Thanks,
Detelin
I don't see anything in the ExtendedGSSContext.inquireSecContext() doc to indicate that it returns the subkey if present for KRB5_GET_SESSION_KEY; do you know from some other source that it does?
In any case, using the subkey is what you need to do. I would look at it this way: your original implementation was not correct, because the WSS Kerberos doc clearly states that the subkey is to be used if present. It just happened to work because the Java 6 Kerberos library did not generate a subkey. Now that one has appeared your bug is revealed, and you have to fix it.
I'm not familiar with WSS, but the doc seems to indicate that you can choose various encodings for the token, and one is to use GSSAPI instead of a Kerberos AP-REQ directly. Perhaps if you had used GSSAPI to begin with, it would have insulated you from this change -- and perhaps switching to it now would be the easiest fix.

SSO confusion - incorporating SSL difficulties

I have a WebSphere on AIX server,
and a simple java client on windows XP (connects to server over http).
I would like to incorporate SSL for client autherization. Mainly, I have a smartcard reader.
The only problem is - the smartcard is used already once to access Windows and we would like to save the trouble for the client to re-enter PIN during client application startup.
I started reading a lot about SSO - which I was assured can help my problem. This led me to reading about WebSphere's support for SPENGO - in their redbooks. Problem is it involves a lot of support from the Active directory people - and they are not keen on helping - and also I fear they're envolvement can slow down the incorporation.
So now I am looking into OpenSSO, WAFFLE, JOSSO and other frameworks that may help me.
But wait - this all seems like a major overspec. All I wanted was to save my client a second prompt to the smartcard.
What I really want is a method - one of the following:
-A Windows XP and above setting that will enable me to retreive the certificate inside the smart card (along with some access to encryption/decryption capabilities to authenticate the certificate).
-Some sort of access to windows to allow me these options
-Perheps, Some sort of java pkcs#11 method that will enable me to get access to the same connection as Windows.
-Is such an ability vendor specific?
Is this even possible? The wikipedia Single sign-on entry http://en.wikipedia.org/wiki/Single_sign-on speaks of SSO with smartcards - but so far I haven't been able to find any way on how to do it. All I know is that my smartcard is prompts a second time if I try to use it with the regular pkcs#11 code.
To sum up:
1. Is there a windows/verndor specific/java to enable me to SSO using the smartcard.
2. If not or if not recommended, what other SSO solution should I use given that I don't want to depend on the Active directory people?
3. In the worst case, where SSO can only be efficiently acheived with Kerberose and ActiveDirectory - what implementation could be less demanding on the ActiveDirectory side?
Thank you.

Spy Java Secure Sockets

I would like to know if there is an easy (or hard) way to spy the secure sockets from a java applet ? (without having the source code)
The goal here is to know exactly what for informations send an (very good obfuscated) applet.
I thought i can simply compile myself a modified java version with a log function but the full source code from java is not available for security reasons...
Set up a proxy server with a security certificate that the applet accepts. Afterwards, you just have to configure your browser to use that proxy and the applet should use the same config.
See Does https prevent man in the middle attacks by proxy server? for how it works technically.
Some things you will need: A proxy than can act as a web server and which is probably reachable with the name of the real server from your browser. You will need to create a valid certificate for this combination which isn't trivial unless the applet is configured to accept certificates from untrusted sources (no CA authority will issue a certificate for, say, "google.com" so that you can feed that to your proxy).
Googling for "man in the middle attack ssl proxy" turns up many links that should be useful.
This article seems to describe an out-of-the-box solution: Understanding Man-In-The-Middle Attacks - Part 4: SSL Hijacking
It doesn't mention applets but Fiddler might fit the bill (from Capturing HTTPS traffic in the clear?)
Just set -Djavax.net.debug=all in the JVM properties. You will get all kinds of output from different layers of the network stack, including the pre-encrypted SSL traffic.
If you're talking about SSL, it wouldn't be secure if that was possible, and it is secure, so it isn't.

CFHTTP: find out supported version of SSL & test auth.net with SSL 3.0

I recently received an email from Authorize.net saying:
During the week of March 16 - 20,
2009, Authorize.Net will be
deprecating all legacy support for the
SSL 2.0 protocol. Changes have
recently been made to the Payment Card
Industry Data Security Standard (PCI
DSS) which have made the use of SSL
2.0 a PCI DSS violation.
So question is: how to make sure that my ColdFusion apps, using cfhttp to communicate with auth.net service, won't become broken in March?
Trying to find out which versions of SSL supported but can not find such info.
Any suggestions?
EDIT
Found discussions: one & two. Seems that only reliable way is upgrading to CF8.
So, other quesiton now: how to test my code with new auth.net protocol? Any ways to switch dev env before going live?
Also I've sent email to dev support of auth.net with these questions. If they'll provide me with solution -- will post it here.
Here is a nice article on www.talkingtree.com regarding the matter:
ColdFusion Protocol Tags CFHTTP, CFINVOKE, CFLDAP support SSLv2
It looks like CF8 is the first version to support SSLv3.
You can also get your hands really dirty and make SSLv3 requests directly, using Java. This would of course require changing working code to emulate functionality that would come naturally with CF8. But if upgrading is not an option for you, maybe this is a viable alternative.
I can't say much about how to test your code against Authorize.net, I'm afraid.
Okay, finally The Gods Have Spoken -- Auth.net Developer replied:
We would recommend that each user
verify their server SSL encryption
protocol settings. If you are unsure
where to find them a Google search of
the server type along with SSL 3.0
should provide helpful information in
this regard. Additionally, the server
support resources should provide this
information.
This change has been released to the
test environment. You may use the
following shared test account for
testing purposes if you wish:
Login ID: xxxxxxxx
Password: xxxxxxxxx
Login URL: https://test.authorize.net
API Login ID: xxxxxxxx
Transaction Key: xxxxxxxxx
Post to URL: https://test.authorize.net/gateway/transact.dll
Note: this is new test account, but I think that all test accounts are changed now, will try to test.
At least, now I am able to test my transactions in sandbox before changes do live, that's what I've wanted.

Categories