A TrustManager/HostnameVerifier that accepts all certificates is a security riskJAVA-S1002
Java uses the TrustManager
and HostnameVerifier
APIs to verify that an SSL connection is properly secured. If a bad implementation of these classes is used, it may allow for malicious hosts to connect to the application.
Bad Practice
This TrustManager
implementation will trust any certificate it is given, meaning even untrusted certificates from a malicious actor could be used.
class TrustAllManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
//Trust any client connecting (no certificate validation)
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
//Trust any remote server (no certificate validation)
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
The HostnameVerifier
interface is used as the final check for the authenticity of a remote connection when all other methods of URL verification have failed. When default certificate validation fails, it is likely that the resulting connection will be insecure and must not be used.
Situations where this may occur include:
- When the URL used to connect to the remote host isn't the same as the one on that host's certificate
- When the remote host server is misconfigured with the wrong certificate.
This implementation of it will trust any hostname it is given:
public class AllHosts implements HostnameVerifier {
public boolean verify(final String hostname, final SSLSession session) {
return true;
}
}
Recommended
To create a TrustManager
without vulnerabilities, using the TrustManagerFactory
API to create a TrustManager
using a keystore is recommended:
KeyStore ks = //Load keystore containing the certificates trusted
SSLContext sc = SSLContext.getInstance("TLS");
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ks);
sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(),null);
When HostnameVerifier needs to be overridden, it is usually because the default certificate based host validation has failed, and the cause is likely remote server side. If possible, consider fixing the problem on the remote server side to obviate the need to handle such issues through HostnameVerifier
. Consider the alternative only if there is no scope to fix the problem at the source.
In the general case, consider using an implementation of HostnameVerifier
that trusts nothing:
public class AllHosts implements HostnameVerifier {
public boolean verify(final String hostname, final SSLSession session) {
return false;
}
}
References
- Web Application Security Consortium - WASC-04 - Insufficient Transport Layer Protection
- CWE-295 - Improper Certificate Validation
- OWASP Top Ten (2021) - Category A02 - Cryptographic Failures
- OWASP Top Ten (2021) - Category A05 - Security Misconfiguration
- FindSecBugs - WEAK_TRUST_MANAGER
- FindSecBugs - WEAK_HOSTNAME_VERIFIER