JDK11 Bug with SSLv3
Jamil Nimeh
jamil.j.nimeh at oracle.com
Tue Dec 11 17:16:41 UTC 2018
Quick follow up. Thomas and I exchanged a couple messages off-alias but
I wanted to summarize it here in case others were following this
thread. The short story: Based on what is in RFC 5246 with respect to
the RSA client key exchange message, the Java client is putting the
correct version in the PreMasterSecret.client_version field.
--Jamil
On 12/10/2018 3:44 PM, Thomas Lußnig wrote:
> Hi,
>
> here is an demo to show the problem.
> a) The problem is an problem between the key exchange message and the
> enabled protocols and the server selected protocol.
> b) In this demo it only check if the protocol of the key exchange is
> TLSv1.2 while SSLv3 is expected.
> c) It also show another issue that the jdk as server does not check if
> the received messages matches the selected protocol version.
> -> I think this does not open an security issue but should be
> verified too, it maybe wanted for compatibility but than it should be
> configurable per connection.
>
> Gruß Thomas Lußnig
>
> package demo;
>
> import java.io.ByteArrayInputStream;
> import java.io.InputStream;
> import java.io.OutputStream;
> import java.io.PrintStream;
> import java.net.ServerSocket;
> import java.security.KeyFactory;
> import java.security.KeyStore;
> import java.security.PrivateKey;
> import java.security.Security;
> import java.security.cert.Certificate;
> import java.security.cert.CertificateFactory;
> import java.security.spec.PKCS8EncodedKeySpec;
> import java.util.Arrays;
> import java.util.Base64;
>
> import javax.net.ssl.KeyManagerFactory;
> import javax.net.ssl.SSLContext;
> import javax.net.ssl.SSLServerSocket;
> import javax.net.ssl.SSLServerSocketFactory;
> import javax.net.ssl.SSLSocket;
> import javax.net.ssl.SSLSocketFactory;
> import javax.net.ssl.TrustManagerFactory;
>
> class CheckPrintStream extends PrintStream {
> public CheckPrintStream() { super(System.out); }
>
> @Override public void write(final byte[] buf, final int off, final
> int len) {
> final String t = new String(buf, off, len);
> if(t.contains("RSA ClientKeyExchange")) {
> if(t.contains("\"client_version\": TLSv1.2")) {
> System.out.println("CHECK Failed");
> final int p = t.indexOf("TLSv1.2");
> super.write(buf, off, p+7);
> super.write('\n');
> }
> else super.write(buf, off, len);
> }
> }
> }
>
> public class SSLv3_TLSv12 {
> static Base64.Decoder b64 = Base64.getDecoder();
> static byte[] rsaKey =
> b64.decode("MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAI64R+LgQkK7kAMRrJh8IbhwXjl0X579vTPJZGUwltqu5tKMpvQE7LDiPP3TAWD1m5ntXHFZKrhiI2QU5kSVGH8yggzK3eFcz8K8p56MpCcqykgM5R/Nt6LSKx/n3snNKuWIOdgOZzl75JXTLp3Mc4IXNFzut6fKopT7N9NRZaktAgMBAAECgYEAiXuD5E3cBqTgCdTQyuNpKF82pWoxYttTk7uBdujjqS2rNVBA0/iaeZq23lyRi3GNvy4kSxx2RsBjD1oCqDZoLUXRyxYqYr2STYZXdz3hKC7p3E7mT+0DgYFWe3nUSlXLGaSpwgXtiH1xLQZ7/jqCMWwDDTibsVcbJDz/Lb2x1xECQQDwku/XTLphWYaTEzw2MkYMxswYDGxIPEM+3hvpzF4Elr5hAOjSfSa66Og89hyokKn5/uRWZ08YbDIuY+BtihSjAkEAl98NN90Gky3p7Kto+39uT9ltzzzpv1+UCyqkY//Q6BrDzoixiNTQtdEnzkXZwYrqe35kIHHIv6gn0t03LDNX7wJBANkdIwuBmauF6mgNsgePc5zQRR1nCMpgaKfyN+rWn/swOHy/H1/nxu5kiEOMMe0HMgAGw/geoEmATAGF7eOt/FUCQHgTOvg4IMKtQo6E1/RAxI8NceywVH+iqgJKLL+Du0BIKRhaq0NsP7gBLl/AinKjytDpFXExhW9DHHlzvfOMhLECQQDmeLkRneJ/Hh5kK5vtpNgE9V+kLfnN2+QhCIWHztFR9VNNgf3JzfZFCruwldZJnCPIdxAi7CpECsk/Bf2zL6XD");
> static byte[] rsaCer =
> b64.decode("MIICHjCCAYegAwIBAgIBATANBgkqhkiG9w0BAQsFADBEMQ0wCwYDVQQLEwRDZXJ0MRIwEAYDVQQKEwlzdWNoZS5vcmcxCzAJBgNVBAYTAkRFMRIwEAYDVQQDEwlsb2NhbGhvc3QwHhcNMTgxMjA5MjIzMDIwWhcNMTgxMjIxMTIxNzAwWjBEMQ0wCwYDVQQLEwRDZXJ0MRIwEAYDVQQKEwlzdWNoZS5vcmcxCzAJBgNVBAYTAkRFMRIwEAYDVQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAI64R+LgQkK7kAMRrJh8IbhwXjl0X579vTPJZGUwltqu5tKMpvQE7LDiPP3TAWD1m5ntXHFZKrhiI2QU5kSVGH8yggzK3eFcz8K8p56MpCcqykgM5R/Nt6LSKx/n3snNKuWIOdgOZzl75JXTLp3Mc4IXNFzut6fKopT7N9NRZaktAgMBAAGjIDAeMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgP4MA0GCSqGSIb3DQEBCwUAA4GBAGFzQL9URFabGys3clkqn6l/tdTzqn6ncG1dL/rhoO1jPAxqGdf7hJ9iPQjPRpdqJl5aawLx9BtWCkdCNXN+Vk4opaGmVNsmQ1eRbZREYEKVKPNquzDIcimDYveYNPRf9shUcU2Z7eAI/GX/uMSlm4XzL7sL4P0v8M/qfja8EQ46");
>
> static {
> Security.setProperty("jdk.tls.disabledAlgorithms", "");
> System.setProperty("javax.net.debug","all");
> }
>
> static void server(final ServerSocket srv, final String[] suites) {
> while(!srv.isClosed()) {
> try( SSLSocket s = (SSLSocket)srv.accept();
> InputStream i = s.getInputStream();
> OutputStream o = s.getOutputStream()) {
> s.setUseClientMode(false);
> if(suites != null) s.setEnabledCipherSuites(suites);
> s.setEnabledProtocols(new String[]{"SSLv3"});
> o.write('s');
> i.read();
> suite = s.getSession().getCipherSuite();
> } catch(final Throwable t) { t.printStackTrace(); }
> }
> }
>
> static SSLContext context(final String keyType) throws Exception {
> final PrivateKey key =
> KeyFactory.getInstance(keyType).generatePrivate(new
> PKCS8EncodedKeySpec(rsaKey));
> final CertificateFactory fact =
> CertificateFactory.getInstance("X.509");
> final Certificate cer = fact.generateCertificate(new
> ByteArrayInputStream(rsaCer));
> final KeyStore ks =
> KeyStore.getInstance(KeyStore.getDefaultType());
> ks.load(null, null);
> final char[] pass = "test".toCharArray();
> ks.setKeyEntry("a", key, pass, new Certificate[]{cer});
> final TrustManagerFactory tmf =
> TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
> tmf.init(ks);
> final KeyManagerFactory kmf =
> KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
> kmf.init(ks, pass);
> final SSLContext c = SSLContext.getInstance("TLS");
> c.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
> return c;
> }
>
> static volatile String suite = null;
>
> static void doCheck(final String[] suites) {
> suite = null;
> System.out.println("START Suites: "+Arrays.toString(suites));
> try {
> final SSLContext c = context("RSA");
> final SSLSocketFactory csf = c.getSocketFactory();
> final SSLServerSocketFactory ssf =
> c.getServerSocketFactory();
> try(final SSLServerSocket srv =
> (SSLServerSocket)ssf.createServerSocket(0, 16)) {
> if(suites != null) srv.setEnabledCipherSuites(suites);
> srv.setEnabledProtocols(new String[]{"SSLv3"});
> new Thread(()->server(srv, suites)).start();
> try( SSLSocket s =
> (SSLSocket)csf.createSocket("localhost", srv.getLocalPort());
> InputStream i = s.getInputStream();
> OutputStream o = s.getOutputStream()) {
> if(suites != null) s.setEnabledCipherSuites(suites);
> s.setEnabledProtocols(new
> String[]{"SSLv3","TLSv1","TLSv1.1","TLSv1.2"});
> o.write('c');
> i.read();
> } catch(final Throwable t) {
> t.printStackTrace(System.out); }
> }
> } catch(final Throwable t) { t.printStackTrace(System.out);
> } finally { System.out.println("DONE Suites:
> "+Arrays.toString(suites)+" used "+suite); }
> }
>
> public static void main(final String[] argc) throws Exception {
> try(final PrintStream check = new CheckPrintStream()) {
> System.setErr(check);
> doCheck(new
> String[]{"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"}); // WORKS
> doCheck(new String[]{"SSL_RSA_WITH_3DES_EDE_CBC_SHA"
> }); // -> Wrong TLSv1.2 in "RSA ClientKeyExchange"
> }
> }
> }
>
>
> On 10.12.2018 20:58:45, Thomas Lußnig wrote:
>> Hi,
>>
>> i am not sure if there is already an bug opened. But i found an error
>> in the SSL-Socket handling.
>> If the ssl client socket enabled SSLv3-TLSv1.2 and the server select
>> SSLv3 the client later on send an
>> "RSA ClientKeyExchange" with version TLSv1.2. I added the relevant
>> parts of the debug log.
>> If there is no bug opened yet i can provide an sample with
>> client/server that demonstrate the bug
>> and can maybe used for regression tests.
>>
>> Gruß Thomas Lußnig
>>
>>
>> 2018-12-10T12:16:41.666
>> javax.net.ssl|DEBUG|15|https://fqdn/path)|2018-12-10 12:16:41.666
>> CET|ClientHello.java:651|Produced ClientHello handshake message (
>> "ClientHello": {
>> "client version" : "TLSv1.2",
>> "random" : "90 B4 FF B0 8E C8 FA 3F D8 15 A3 73 13 78
>> 38 D5 3A FB 49 68 28 ED B1 95 3C 3E 24 0C DD 64 A2 95",
>> "session id" : "",
>> "cipher suites" : "[SSL_RSA_WITH_3DES_EDE_CBC_SHA(0x000A),
>> TLS_EMPTY_RENEGOTIATION_INFO_SCSV(0x00FF)]",
>> "compression methods" : "00",
>> ...
>>
>> 2018-12-10T12:16:41.688
>> javax.net.ssl|DEBUG|15|https://fqdn/path)|2018-12-10 12:16:41.688
>> CET|ServerHello.java:866|Consuming ServerHello handshake message (
>> "ServerHello": {
>> "server version" : "SSLv3",
>> "random" : "5C 37 37 A9 EA DD D7 67 28 15 D3 DF 5F 3F
>> 13 E2 34 88 93 67 16 FD 4F 76 A6 08 11 BE 36 E3 B4 26",
>> "session id" : "1D 5F B9 F7 EC DE 8E D9 38 52 AB FF 04 A1
>> 24 1D",
>> "cipher suite" : "SSL_RSA_WITH_3DES_EDE_CBC_SHA(0x000A)",
>> "compression methods" : "00",
>> "extensions" : [
>> <no extension>
>> ]
>> }
>> )
>>
>> 2018-12-10T12:16:41.699
>> javax.net.ssl|DEBUG|15|https://fqdn/path)|2018-12-10 12:16:41.699
>> CET|CertificateMessage.java:358|Consuming server Certificate
>> handshake message (
>> "Certificates": [
>> "certificate" : {
>> "version" : "v3",
>> "serial number" : "02 6F D4 BA 63 70 2F 13 00 91 5D E4",
>> "signature algorithm": "SHA256withRSA",
>> "issuer" : "CN=VR IDENT CLASS 3 CA 2010, OU=VR IDENT,
>> O=GAD EG, C=DE",
>> "not before" : "2017-07-20 01:33:58.000 CEST",
>> ...
>>
>> 2018-12-10T12:16:41.854
>> javax.net.ssl|DEBUG|15|https://fqdn/path)|2018-12-10 12:16:41.853
>> CET|X509TrustManagerImpl.java:242|Found trusted certificate (
>> "certificate" : {
>> "version" : "v3",
>> "serial number" : "02 6F D4 BA 63 70 2F 13 00 91 5D E4",
>> ...
>>
>> 2018-12-10T12:16:41.856
>> javax.net.ssl|DEBUG|15|https://fqdn/path)|2018-12-10 12:16:41.856
>> CET|RSAClientKeyExchange.java:195|Produced RSA ClientKeyExchange
>> handshake message (
>> "RSA ClientKeyExchange": {
>> "client_version": TLSv1.2
>> "encncrypted": {
>> 0000: 52 2E C4 EB 8C 65 06 77 47 5D 9E 10 56 95 8A 6E
>> R....e.wG]..V..n
>> 0010: 03 D0 70 8D 73 51 93 F7 8B F7 73 55 25 AC E4 0C
>> ..p.sQ....sU%...
>> 0020: 34 68 26 01 E0 40 64 B5 82 C6 1C 7C 04 81 E3 15
>> 4h&.. at d.........
>> ...
>>
>>
More information about the security-dev
mailing list