logo

Database

Insecure encryption algorithm - SSL/TLS

Need

Use of a maintained HTTP client restricted to current TLS versions

Context

• Usage of Kotlin 1.9+ on the JVM for building application services

• Usage of the Apache HttpClient 4.x library for outbound HTTP requests

• Usage of the java.net.http client included in Java 11+

Description

1. Non compliant code

import org.apache.http.client.methods.HttpGet
import org.apache.http.impl.client.DefaultHttpClient
import org.apache.http.util.EntityUtils

fun fetchStatus(url: String): String {
    // Deprecated client with a legacy TLS configuration and no security updates
    val client = DefaultHttpClient()
    val response = client.execute(HttpGet(url))...

The `fetchStatus` function below sends its requests with `DefaultHttpClient`, from Apache HttpClient 4.x. `DefaultHttpClient` was deprecated in HttpClient 4.3, more than ten years ago, and it no longer receives security fixes. Its TLS configuration comes from the legacy `SSLSocketFactory` of the library, which predates the TLS improvements of later versions: depending on the Java runtime, it can negotiate outdated protocol versions and cipher suites, and its hostname verification can be replaced with the permissive `ALLOW_ALL_HOSTNAME_VERIFIER` with a single setter. A client that negotiates weak protocols or cipher suites lets an attacker on the network path downgrade the connection and decrypt or modify the traffic, including credentials and tokens sent to the remote service.

2. Steps

• Replace `DefaultHttpClient` and other deprecated Apache HttpClient 4.x classes with `java.net.http.HttpClient` or Apache HttpClient 5.

• Restrict the client to `TLSv1.3` and `TLSv1.2` with `SSLParameters.protocols` or the equivalent TLS strategy of the library.

• Keep the default certificate and host name verification, and never install a permissive hostname verifier.

• Create HTTP clients once and reuse them instead of building one per request.

• Keep the JDK and the HTTP client library up to date so TLS fixes are applied.

3. Secure code example

import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
import java.time.Duration
import javax.net.ssl.SSLParameters

// Maintained JDK client that only negotiates TLS 1.3 and 1.2...

The corrected function uses `java.net.http.HttpClient`, the HTTP client included in the JDK since Java 11. It is maintained together with the runtime, so it receives TLS fixes with every JDK update, and it verifies the server certificate and host name by default. The client is built with `SSLParameters` that only allow `TLSv1.3` and `TLSv1.2`, so it refuses to negotiate SSLv3, TLS 1.0 or TLS 1.1 even if the server or a network attacker offers them. It also sets a connection timeout and never follows redirects to plain HTTP. The client is created once and reused, which keeps connections pooled. Applications that need Apache HttpClient can move to HttpClient 5 with `HttpClients.custom()` and a TLS strategy restricted to the same versions.