Mission Impossible: Zero-Configuration SSL

SSL (let’s call it that, even though SSL 2.0 and SSL 3.0 were long replaced by TLS 1.0–1.3 protocols) support was implemented in MySQL in 2001, so MariaDB (born in 2009) always had it. But over more than twenty years of SSL support there was one huge problem with it. It required tedious manual configuration, so most users never bothered and accepted the fact that their queries and data were sent unprotected. Which might have been slightly risky in 2001, but is definitely reckless in 2023.

The traditional approach

Let’s see. First, the user installing MariaDB or MySQL has to generate a private key and a certificate. Granted, it’s the simplest step of all, just copy few commands from the manual. And MySQL 8.0 could even do it automatically for you. But it’s just the beginning. You see, SSL’s sole purpose is to protect the connection from an attacker who sits between the client and the server (MitM, Man-in-the-Middle). If there can be no attacker in the middle, one does not need SSL. And if there is one — this attacker can replace the certificate that the server is sending to the client, and gain the ability to intercept and snoop on the connection that both the client and a server think is securely encrypted.

To prevent this from happening, the client must verify that the certificate indeed belongs to the server it is talking to. This is enabled with the --ssl-verify-server-cert option (renamed to --ssl-mode=VERIFY_IDENTITY in MySQL). And fundamentally, verifying a certificate means verifying a signature. It has to be signed by a trusted certificate authority (CA). Meaning, the user has to buy a proper certificate from an authority that their SSL implementation trusts. Or get one for free from Let’s Encrypt, which offers its own special set of hoops for users to jump through. Or the user can be their own CA, generate a certificate, and manually install it on all clients in the trusted certificate store.

Because of that, only a small number of MariaDB users have actually enabled SSL, and even a smaller number have properly signed certificates to enable --ssl-verify-server-cert. Others either opted to not use SSL at all, or to not verify certificates (which is only marginally better than the first choice).

Zero-Configuration SSL

This will change in 11.3. In this new MariaDB version, one can have the cake and eat it too, err, have SSL enabled with verified certificates and do nothing whatsoever to configure it. But how does it work? How can MariaDB break the fundamental SSL requirement for a trusted signatory authority? The solution lies in the fact that a MariaDB client connecting to a MariaDB server differs from a general case of, say, your browser visiting https://mariadb.org.

In the absolute majority of the cases the client and the server have a shared secret — something that only they know, but the attacker does not. Indeed, the client needs to authenticate itself to the server by proving that it knows the account password. And now in 11.3 MariaDB server and clients can additionally use this password to verify that the SSL certificate is, indeed, coming from the server that the client wants to talk to.

The protocol

This is how it works. The client connects to the server and they establish an SSL connection. If the client can verify the certificate using a CA signature or a fingerprint (another new feature in 11.3) — verification ends here, the certificate is verified. Similarly if the connection is done via a secure local transport — unix sockets or named pipes. Otherwise the certificate is in doubt, but the client won’t immediately disconnect from the server as it would’ve done before. If the server requests a secure authentication (mysql_native_password or ed25519, they are MitM-proof even without SSL) the client can carry on. But the client will disconnect if the server wants to switch to an insecure authentication — it will refuse to send a plain-text password over an insecure SSL connection. After the successful secure authentication, the server will send to the client this signature:

SHA256("password hash", scramble, "certificate fingerprint")

The client knows all these three values, it can calculate the same signature, compare with what the server has sent, and verify that the server, indeed, knows the password (the client wasn’t redirected to an evil server), and the certificate was not replaced by an attacker (fingerprint didn’t change).

Now MariaDB clients can verify the server certificate even if it’s self-signed. This allowed us to enable SSL on the server by default, never mind if the certificates are not provided by the user, the server will generate them automatically. And enable SSL on the client by default with full MitM-proof certificate verification. Without a user doing or configuring anything. Mission accomplished.

Limitations

Are there disadvantages? Unfortunately, yes. A small number of users will be affected negatively by the following:

  • If you use the PAM or gssapi plugins, this automatic certificate verification won’t work. You’ll need to use the old way with a CA or disable certificate verification altogether.
  • It’s common in test environments to have password-less accounts. Automatic certificate verification won’t work without a password (and, indeed, an attacker won’t need to break SSL if they can simply legally login without a password). MariaDB command-line clients will warn and automatically disable certificate verification in this case.
  • Normally SSL has a neglectable effect on the connection speed. But if your application uses lots of very short-lived connections (like, connect, one primary key lookup, disconnect) then the SSL handshake overhead might be very noticeable. Disable SSL or use a connection pool.

But most users will simply find themselves in a more secure world, having their connection to a database automatically encrypted and protected from MitM attacks.


Disclaimer: This is currently in the 11.3.0 preview release. Though unlikely, it might be removed from the final 11.3.1 release, as per MariaDB release model.

Update: it did not get into 11.3.1. As it is a critical security related feature, we wanted to be very sure, more than usual, that there are no flaws in it, and we consulted various experts in field of cryptographic protocols. And didn’t manage to get the feedback in time for 11.3.1 release.

Update 2: we have got all the feedback we were waiting for and this feature was released in 11.4.1