How to use HostnameVerifier?
Asked Answered
K

3

10

I am experimenting right now with SSL configs using KeyManager and TrustManager, everything seems clear to me except the HostNameVerifier part.

I have read the followings:
https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/HostnameVerifier.html
https://lightbend.github.io/ssl-config/HostnameVerification.html

So basically it comes in effect when the requested URL and the URL in the cert are mismatch.

What is the best practice to handle this?

 new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
          // some code
        }
    };

From security(like man in the middle attack) point of view I think it must return false all the time.But in this case what is the purpose of this whole thing?
However surfing on the internet most of the time I come accross solutions that return a raw 'true' (without any work on the arguments).

So its confusing to me when,why and how should I use it.

Could you elaborate it please?

Kimmy answered 26/10, 2019 at 8:56 Comment(0)
S
10

From security(like man in the middle attack) point of view I think it must return false all the time.

Almost correct. This method is only called if the default verification detects a problem. In almost all cases such a problem means that the connection should be aborted to keep it secure.

However surfing on the internet most of the time I come accross solutions that return a raw 'true' (without any work on the arguments).

This is wrong almost every time. The authors of such code usually don't understand the implications (possible MITM as you correctly said) and just want their code to work somehow. Yes, it will work but it will also work when it should not, i.e. it is insecure.

Typical reasons that the default verification fails are that the server is improperly configured with the wrong certificate or that the server is accessed with the wrong hostname (i.e. not the one in the certificate).

So its confusing to me when,why and how should I use it.

You should use it only if you know that the host is returning a certificate with the wrong subject but you also know what exactly will be wrong and will properly verify this expectation inside your implementation.

Of course, it is much better to not work around in all applications accessing the server but instead to fix the real problem. Depending on the real cause of the problem this usually means either fixing the certificate at the server or fixing the hostname used to access the server.

Stillness answered 26/10, 2019 at 9:20 Comment(5)
one such use case is testing. More often then not, Beta systems will be a copy of Prod, with little regard to what breaks when it's a 1:1 copy, like certificates... I've made a pretty penny developing all sorts of SSL test clients with a hostname warning (non fatal). I think in the vast majority of cases, we are fine if someone does a MITM on a test client (if they manage to get into a test box, if they think it's even worth it...)Jordans
@DraxDomax: The problem is not that such code gets used in testing but that the same code then gets used in production - since it works. It is much better to have a realistic test setup, like overriding the mapping between hostname and IP (for example with a local hosts file) so that the correct hostname can be used, instead of using a different hostname to access the service. Also using the wrong hostname can also cause problems with servers sensitiv to SNI (the hostname send in the TLS handshake): they might provide a different web application or simply fail if the wrong hostname is used.Stillness
I know I come across as rude (perhaps due to me being on the spectrum) but I just want to re-emphasize, in the most friendly and cool way :) that I wrote "test clients" - testware, which has no business getting shipped anywhere :) Yeah, I totally would not respect a bypassed hostnames verifier on a production client - even if it has a switch, I know someone will leave that switch open JUST when we don't need to (Murphy's Law)!Jordans
as for realistic - you have to be realistic about the kind of people you are working with. They barely code in Java, let alone resolve any SSL problems. I prefer giving them the power to author tests rapidly (remember their boss has a quota of how many tests they need to automate this week), with the least help required (Devs and DevOps usually don't give a pluck about QA and rarely help with anything). ******** Penetration testing is a different concern and is done by it's own framework and by specialistsJordans
@DraxDomax: If it stays in a test environment this is likely not a security problem. It might still result in the mentioned functionality problem though if the hostname in the TLS handshake (SNI) does not match the hostname for the specific server setup.Stillness
W
4

Check if the session host is what we expect.

public boolean verify(String hostname, SSLSession session) {
   return hostname.equals(session.getPeerHost());
}
Wire answered 11/6, 2021 at 12:22 Comment(1)
hostname is ALWAYS equal to session.getPeerHost(), even if a MITM attack is taking place! This snippet is identical to returning true, which you should NEVER do!Layout
L
1

If you're just trying to make the system trust a specific certificate in place of the expected hostname, you could try this (Kotlin) code:

            return if (hostname == "proxy.example.com") { // the host that is being connected to over TCP
                val cert = session.peerCertificates[0] as? X509Certificate ?: return false
                cert.subjectAlternativeNames.contains(listOf(2, "subject.example.com")) // the certificate that is being served
            } else {
                false
            }

It won't work for some old certificates that use CN identification only (not SAN), but this would be trivial to fix.

Layout answered 14/6, 2023 at 13:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.