5

I am in the process of phasing out support for TLS 1.0 and TLS 1.1 for a web application.

I would like to detect users this will impact based on the connections they are making to my servers.

I am running Tomcat 7 and Java 8.

How do I detect the TLS version of an HttpServletRequest?

Alain O'Dea
  • 21,033
  • 1
  • 58
  • 84
  • 1
    This is an old question. I am afraid that tomcat does not publish the `SSLSession`. Are you using tomcat standalone or a proxy like apache or nginx? – pedrofb Jan 24 '17 at 06:06
  • Using Tomcat behind an AWS ELB. I suppose if I drop apache or nginx in I can run TLS 1.2 detection in a module? – Alain O'Dea Jan 24 '17 at 12:05
  • @pedrofb and by old you mean has been asked in various ways on various forums with no solid answer to date. I looked at the Servlet API source and Tomcat source and found no good answer. It looks like deep hackery with reflection might solve this, but it would be very brittle. – Alain O'Dea Jan 24 '17 at 12:08
  • FWIW I'll accept brittle because it only has to work until the cutover date which is soon and then affected users can call help desk. – Alain O'Dea Jan 24 '17 at 12:12
  • I was looking for some time ago trying to recover the SSLSession without luck. There is probably some workaround to get it, but I do not know how. I could not find any hint – pedrofb Jan 24 '17 at 17:52
  • 1
    Installing an apache to deal with SSL instead of tomcat could solve the question. Apache environment variable SSL_PROTOCOL can be exported to tomcat in attribute `org.apache.tomcat.util.net.secure_protocol_version` (using mod_jk module through tomcat's AJP connector. See https://tomcat.apache.org/connectors-doc/reference/apache.html). – pedrofb Jan 24 '17 at 17:52

1 Answers1

1

This is not practical to do in Java. It requires modifying the JSSE implementation or plugging in an alternative.

I eventually solved this by deploying How's My SSL and using cross-domain AJAX from the client-side to check the SSL state and report it to my app server.

You need to have unproxied direct requests from a client to properly assess the state of their SSL. Do NOT put an HTTPS load balancer in front of How's My SSL. It will break it and give you incorrect results.

Here is a snippet of client-side JavaScript that should work using the public How's My SSL service (I recommend deploying your own):

$.getJson('https://www.howsmyssl.com/a/check')
.done(function (result) {
    $.post('/logs', {
                    name: 'howsmyssl',
                    level: 'info',
                    message: result
    });
})
.fail(function(err) {
    $.post('/logs', {
                    name: 'howsmyssl',
                    level: 'error',
                    message: 'could not reach howsmyssl'
    });
});

You will need to have a REST endpoint running at /logs on your app server that can receive a POST to capture this. You can change that path and the format of the message to your heart's content. This endpoint should be authenticated and should enrich the logs with the event time, the authenticated principal (user), and possibly other information like the IP address.

The contents of result look like this (pretty-printed to make it easier to read):

{
    "given_cipher_suites": [
        "TLS_GREASE_IS_THE_WORD_8A",
        "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
        "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
        "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
        "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
        "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
        "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
        "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
        "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
        "TLS_RSA_WITH_AES_128_GCM_SHA256",
        "TLS_RSA_WITH_AES_256_GCM_SHA384",
        "TLS_RSA_WITH_AES_128_CBC_SHA",
        "TLS_RSA_WITH_AES_256_CBC_SHA",
        "TLS_RSA_WITH_3DES_EDE_CBC_SHA"
    ],
    "ephemeral_keys_supported": true,
    "session_ticket_supported": true,
    "tls_compression_supported": false,
    "unknown_cipher_suite_supported": false,
    "beast_vuln": false,
    "able_to_detect_n_minus_one_splitting": false,
    "insecure_cipher_suites": {
    },
    "tls_version": "TLS 1.2",
    "rating": "Probably Okay"
}

You can log this to a log aggregator or a database to query it later to find specific users to call or email. You could even alert users to the gaps in their browser's TLS within your app and specifically highlight the approaching TLS 1.2 deadline and steps they can take to update their browser to compensate.

Alain O'Dea
  • 21,033
  • 1
  • 58
  • 84