JDK11 Bug with SSLv3
Thomas Lußnig
openjdk at suche.org
Mon Dec 10 23:44:03 UTC 2018
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