Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Authentication errors when accessing token endpoint from JVM

We run a web application with a JVM backend (Java 7 update 75; code is in Scala, but I don't believe this is relevant). We use Google for authentication via Oauth.

There have been a handful of days over the last couple of months on which we have been intermittently unable to authenticate users.

The redirect to and from Google is successful, but when we try to call the token_endpoint at https://www.googleapis.com/oauth2/v4/token to validate the authentication we sometimes get the following exception: javax.net.ssl.SSLHandshakeException: server certificate change is restrictedduring renegotiation.

This comment on another question led me to find a JDK bug that can manifest as this exception (What means "javax.net.ssl.SSLHandshakeException: server certificate change is restrictedduring renegotiation" and how to prevent it?).

My working hypothesis is:

The bug (https://bugs.openjdk.java.net/browse/JDK-8072385) means that only the first entry in the Subject Alternative Name (SAN) list is checked. The exception above is thrown when the hostname being verified is in the SAN list, but not at the top of the list.

Yesterday (27th May 2015 from ) we saw two different certificates being intermittently served from www.googleapis.com. The first (serial 67:1a:d6:10:cd:1a:06:cc) had an SAN list of DNS:*.googleapis.com, DNS:*.clients6.google.com, DNS:*.cloudendpointsapis.com, DNS:cloudendpointsapis.com, DNS:googleapis.com whilst the second (serial 61:db:c8:52:b4:77:cf:78) had a SAN list of: DNS:*.storage.googleapis.com, DNS:*.commondatastorage.googleapis.com, DNS:*.googleapis.com.

Due to the bug in the JVM, we can validate the first certificate, but the exception is thrown with the second (despite being perfectly valid) as *.googleapis.com is not the first entry in the SAN list.

The fix is in the yet to be released 7u85 (no mention of when this will be available).

I've downgraded a single node of our cluster to 7u65, but the certificate seemed to be reverted at around the time we did this (last error we saw was 22:20GMT) so it's hard to pin down an affirmative fix.

Has anyone else experienced this or something similar and have any other workaround other than downgrading (downgrading removes various other SSL/TLS checks)?

like image 900
sihil Avatar asked May 28 '15 14:05

sihil


1 Answers

I am not really sure that your problem is related to a JVM bug.

There is a fix in Java 6 and above for CVE-2014-6457, "Triple Handshake attack against TLS/SSL connections (JSSE, 8037066)", prevents peer certificates changing during renegotiation.

Problem explanation:

A security vulnerability in all versions of the Transport Layer Security (TLS) protocol (including the older Secure Socket Layer (SSLv3)) can allow Man-In-The-Middle (MITM) type attacks where chosen plain text is injected as a prefix to a TLS connection. This vulnerability does not allow an attacker to decrypt or modify the intercepted network communication once the client and server have successfully negotiated a session between themselves.

However, if the potentially changed certificate is for the same identity as the last seen certificate then the connection is allowed.

Two identities are considered equal in this case:

  • There is a subject alternative name specified in both certificates which is an IP address and the IP address in both certificates is the same.
  • There is a subject alternative name specified in both certificates which is a DNS name and the DNS name in both certificates is the same.
  • The subject and issuer fields are present in both certificates and contain identical subject and issuer values.

In other conditions (the identity of the certificate has changed) then a javax.net.ssl.SSLHandshakeException: server certificate change is restricted during renegotiation exception is raised.

Workaround:

  • Disable renegotiation (not recommended) applying the following JVM argument: -Djdk.tls.allowUnsafeServerCertChange=true it disables the unsafe server certificate protection.
  • Disable SSLv3 in outgoing HTTPS connections, Java 7 supports TLSv1.1 and TLSv1.2 in client mode but defaults to using TLSv1 in the TLS handshake. We should use TLSv1.1 and TLSv1.2 in client mode TLS in java 7 as well. Java 8 enables TLSv1.1 and TLSv1.2 in client mode(in addition to SSLv3 and TLSv1) and uses TLSv1.2 by default in TLS handshake. If you are creating the connection programatically and setting a socket factory use TLS instead of SSL.

Anyway, update your post with your google oauth client code before calling the token_endpoint to validate the authentication to see what might be happening.

like image 168
vzamanillo Avatar answered Nov 14 '22 23:11

vzamanillo