Shib IdP - Metadata Download and Java 1.7.0_85

Takeshi NISHIMURA takeshi at nii.ac.jp
Tue Jul 28 07:04:34 EDT 2015


I have written a bug report as below and submitted to bugreport.java.com.
If you know more appropriate place to report, please spread this info.

Takeshi

Synopsis:
Preserving mechanism of original hostnames in SSLSocketImpl fails

Full OS version:
Linux host.example.org 2.6.18-406.el5 #1 SMP Tue Jun 2 17:26:20 EDT 2015 i686 i686 i386 GNU/Linux

Development Kit or Runtime version:
--
java version "1.8.0_51"
Java(TM) SE Runtime Environment (build 1.8.0_51-b16)
Java HotSpot(TM) Client VM (build 25.51-b03, mixed mode)
--

Description:
--
Preserving mechanism of original hostnames in SSLSocketImpl, which is introduced in order to fix CVE-2015-2625, does not work as expected.

You can access the original hostname via JavaNetAccess.getOriginalHostName(InetAddress ia) but it always returns null.

As a consequence, sslSession.getPeerHost() and other methods depending on that returns IP address instead of hostname.

If you call createSocket(String host, int port) instead of createSocket(InetAddress ia, int port), the original hostname is stored in this.host in SSLSocketImpl.java:420 and JavaNetAccess.getOriginalHostName() will be never called and it works as expected.
--

Frequency: Always

Steps to Reproduce: Just execute my test case.

Expected Result:
--
JavaNetAccess.getOriginalHostName() returns original hostname hence sslSession.getPeerHost() can return it.

$ java GetPeerHostTest
InetAddress: www.oracle.com/23.67.182.140
via JavaNetAccess: www.oracle.com
getPeerHost(): www.oracle.com
--

Actual Result:
--
JavaNetAccess.getOriginalHostName() returns null and sslSession.getPeerHost() returns IP address.

$ java GetPeerHostTest
InetAddress: www.oracle.com/23.67.182.140
via JavaNetAccess: null
getPeerHost(): 23.67.182.140
--

Source code for an executable test case: GetPeerHostTest.java (attached)

Workaround:
--
Set -Djdk.tls.trustNameService=true option.
Result:
InetAddress: www.oracle.com/23.67.182.140
via JavaNetAccess: null
getPeerHost(): www.oracle.com
--

On 2015/07/25 3:32, Takeshi NISHIMURA wrote:
> Hi Brent,
>
> Thank you for digging deeper.
> Preserving mechanism of originalHostName via sun.misc.JavaNetAccess, added in [1], is totally broken. Because putting hostName into InetAddressHolder by constructor or init() never happen.
>
> Only one (or to be more precise 3) successful path is to set this.host directly in [2]. This can be achieved by constructor with argument "String host".
>
> That is,
>
>> SSLSocket sslSocket = (SSLSocket)sslContext.getSocketFactory().createSocket("metadata.gakunin.nii.ac.jp", 443);
>
> will succeed, but
>
>> SSLSocket sslSocket = (SSLSocket)sslContext.getSocketFactory().createSocket(InetAddress.getByName("metadata.gakunin.nii.ac.jp"), 443);
>
> will fail.
>
> Takeshi
>
> [1] http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/a25640f4e518
> [2] http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/3eb4e20b34cb/src/share/classes/sun/security/ssl/SSLSocketImpl.java
>
>> On 7/23/15 2:20 AM, Brent Putman wrote:
>>> By default SSLSession#getPeerHost() now returns the IP address, at
>>> least in conjunction with how the socket factory is used in
>>> HttpClient v3.  I think I read something earlier this evening that
>>> said the old quirky IP address behavior you experienced was only
>>> tripped if you used the socket factory methods that take an
>>> InetAddress as opposed to a String, or something.  So that's probably
>>> what the HttpClient is doing.
>>
>> Just following up on this:  Depending on how the JSSE SSLSocketFactory
>> is called, it doesn't *always* happen.  (To me means more evidence that
>> this is a bug).  In v2 our HttpClient factory has:
>>
>>
>>          if (timeout == 0) {
>>              // Here 'host' is just a String
>>              Socket socket = socketfactory.createSocket(host, port, localHost, localPort);
>>              verifyHostname(socket);
>>              return socket;
>>          } else {
>>              Socket socket = socketfactory.createSocket();
>>              SocketAddress localaddr = new InetSocketAddress(localHost, localPort);
>>              // Here host (String) + port (int) converted to InetSocketAddress
>>              SocketAddress remoteaddr = new InetSocketAddress(host, port);
>>              socket.bind(localaddr);
>>              socket.connect(remoteaddr, timeout);
>>              verifyHostname(socket);
>>              return socket;
>>          }
>>
>>
>> If you fall into the first block, getPeerHost() behaves as always,
>> returning the hostname, and everything works as it should.  If you do
>> have a non-zero timeout (which you always want), getPeerHost() returns
>> the IP address.
>>
>> So in terms of the broader effect of this, it's complicated.  It's
>> going to depend on how the caller is using SSLSocketFactory.  I did see
>> something about the original IP addr quirk depending on exactly how the
>> InetAddress instances passed to the factory are created. [1]  The above
>> behavior is probably related.
>>
>> An SSLSocketFactory has basically 6 different overloaded
>> createSocket(...) methods, plus the above use of Socket#connect(...),
>> etc.  We just happen to be unlucky bastards using the bad one and/or in
>> the bad way.
>>
>> So vt-ldap/ldaptive may not be affected here, it depends on exactly how
>> the SSLSocketFactory is being used.
>>
>>
>> [1] http://mail.openjdk.java.net/pipermail/security-dev/2014-November/011377.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: GetPeerHostTest.java
Type: text/x-java
Size: 1136 bytes
Desc: not available
URL: <http://shibboleth.net/pipermail/users/attachments/20150728/93384dcf/attachment-0001.bin>


More information about the users mailing list