Unsafe certificate trustΒΆ
ID: java/unsafe-cert-trust
Kind: problem
Severity: warning
Precision: medium
Tags:
- security
- external/cwe/cwe-273
Query suites:
- java-security-extended.qls
- java-security-and-quality.qls
Click to see the query in the CodeQL repository
Java offers two mechanisms for SSL authentication - trust manager and hostname verifier (the later is checked by the java/insecure-hostname-verifier query). The trust manager validates the peerβs certificate chain while hostname verification establishes that the hostname in the URL matches the hostname in the serverβs identification.
When SSLSocket or SSLEngine are created without a secure setEndpointIdentificationAlgorithm, hostname verification is disabled by default.
This query checks whether setEndpointIdentificationAlgorithm is missing, thereby making the application vulnerable to man-in-the-middle attacks. The query also covers insecure configurations of com.rabbitmq.client.ConnectionFactory.
RecommendationΒΆ
Validate SSL certificates in SSL authentication.
ExampleΒΆ
The following two examples show two ways of configuring SSLSocket/SSLEngine. In the βBADβ case, setEndpointIdentificationAlgorithm is not called, thus no hostname verification takes place. In the βGOODβ case, setEndpointIdentificationAlgorithm is called.
public static void main(String[] args) {
{
SSLContext sslContext = SSLContext.getInstance("TLS");
SSLEngine sslEngine = sslContext.createSSLEngine();
SSLParameters sslParameters = sslEngine.getSSLParameters();
sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); //GOOD: Set a valid endpointIdentificationAlgorithm for SSL engine to trigger hostname verification
sslEngine.setSSLParameters(sslParameters);
}
{
SSLContext sslContext = SSLContext.getInstance("TLS");
SSLEngine sslEngine = sslContext.createSSLEngine(); //BAD: No endpointIdentificationAlgorithm set
}
{
SSLContext sslContext = SSLContext.getInstance("TLS");
final SSLSocketFactory socketFactory = sslContext.getSocketFactory();
SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443);
SSLParameters sslParameters = sslEngine.getSSLParameters();
sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); //GOOD: Set a valid endpointIdentificationAlgorithm for SSL socket to trigger hostname verification
socket.setSSLParameters(sslParameters);
}
{
com.rabbitmq.client.ConnectionFactory connectionFactory = new com.rabbitmq.client.ConnectionFactory();
connectionFactory.useSslProtocol();
connectionFactory.enableHostnameVerification(); //GOOD: Enable hostname verification for rabbitmq ConnectionFactory
}
{
com.rabbitmq.client.ConnectionFactory connectionFactory = new com.rabbitmq.client.ConnectionFactory();
connectionFactory.useSslProtocol(); //BAD: Hostname verification for rabbitmq ConnectionFactory is not enabled
}
}
ReferencesΒΆ
SSLParameters.setEndpointIdentificationAlgorithm documentation.
RabbitMQ: ConnectionFactory.enableHostnameVerification documentation.
RabbitMQ: Using TLS in the Java Client.
CVE-2018-17187: Apache Qpid Proton-J transport issue with hostname verification.
CVE-2018-8034: Apache Tomcat - host name verification when using TLS with the WebSocket client.
CVE-2018-11087: Pivotal Spring AMQP vulnerability due to lack of hostname validation.
CVE-2018-11775: TLS hostname verification issue when using the Apache ActiveMQ Client.
Common Weakness Enumeration: CWE-273.