[MDEV-28634] Client's --ssl-* options (without --ssl-verify-server-cert) are silently ignored if TLS is not possible Created: 2020-07-11 Updated: 2024-02-05 Resolved: 2024-02-05 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Scripts & Clients, SSL |
| Fix Version/s: | 11.4.1 |
| Type: | Task | Priority: | Critical |
| Reporter: | Geoff Montee (Inactive) | Assignee: | Sergei Golubchik |
| Resolution: | Fixed | Votes: | 0 |
| Labels: | skysql | ||
| Issue Links: |
|
||||||||||||||||||||||||||||||||||||||||
| Description |
|
If the client provides --ssl-* options, but a TLS connection to the server is not possible, then the client simply silently ignores the provided --ssl-* options if the --ssl-verify-server-cert option is not also provided. The user may think that their connection is encrypted, but it is not. The current behavior is probably the "expected" behavior according to Engineering. See Consider an example: if you typed https://mybank.com into your browser's URL bar, would you be happy if the browser silently used an unencrypted connection, even though you requested HTTPS? This is basically what MariaDB's clients are doing. For example, let's say that TLS is not enabled on our server:
If a client tries to connect via TLS, then they will not see an error, and their connection will be unencrypted:
The client will only see an error if they also provide the --ssl-verify-server-cert option:
MySQL fixed this problem by introducing the --ssl-mode client option in MySQL 5.7.11 that provides more configurable TLS behavior. https://dev.mysql.com/doc/refman/5.7/en/connection-options.html#option_general_ssl-mode Part of the new MySQL behavior made it so that if the client specifies the --ssl-ca or --ssl-capath option, then that will imply --ssl-mode=VERIFY_CA. by default.
In my opinion, we should take one of the following actions:
|
| Comments |
| Comment by Ralf Gebhardt [ 2021-12-27 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
serg, from a user point of view it might not be clear that -ssl is just a "preferred" setting, but not requiring SSL. MySQL is using --ssl-mode, which gives the client user more control of what is expected. We should move towards this way or to use --ssl with the option to define different modes, with a default which requires SSL. I have seen What would be the required options for a secure SSL connection from your point of view? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Golubchik [ 2022-01-03 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
One has to specify --ssl-verify-server-cert to make sure the connection is properly encrypted and nobody but the server can see the data. We could, perhaps, introduce something like --ssl-verify-server-cert=auto (or, more in line with other options --autoset-ssl-verify-server-cert) which will behave as ON if ssl is enabled by any other option and OFF otherwise. And make this the default behavior. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by pgnd [ 2023-02-02 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
this seems to be a closer fit @ but that's closed, and this is marked related ...
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Geoff Montee (Inactive) [ 2023-02-02 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hi pgnd,
Have you tried specifying the --ssl-verify-server-set and --ssl options with the skip prefix, like this?:
You might also be able to set them to 0 directly:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Daniel Lenski [ 2023-06-14 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
GeoffMontee wrote:
ralf.gebhardt wrote:
This is essentially a totally silent TLS → non-TLS downgrade. Because the server's TLS capability is inferred from the capabilities in its (plaintext) server greeting packet, it's trivial for an on-path or pervasive attacker to opportunistically downgrade connections from any clients that have specified --ssl but not --ssl-verify-server-cert. It's 2023. It's completely at odds with user expectations of any TLS-enabled client to specify the --ssl option ("Yes, I want to use SSL/TLS for all communications with this server") and have it silently downgraded to an unencrypted connection. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Daniel Lenski [ 2023-06-14 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Admins should consider moving this issue to https://jira.mariadb.org/projects/CONC, since it's an issue with Connector/C rather than the MariaDB server. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Daniel Lenski [ 2023-06-15 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I've created mariadb-connector-c PR #224 as a proposed fix for this vulnerability. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Golubchik [ 2023-06-17 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
dlenski, I generally agree with you. --ssl on itself doesn't guarantee anything without --ssl-verify-server-cert, it's 2023, and so on. Still, from a user point of view — they had MariaDB working, ssl enabled, so "everything was secure". Then after an upgrade the application is down, clients cannot connect anymore. Who broke user application (mission critical, of course) — we did. And note that after 10.10 ( I know that you're right and ssl should be enforced and certs should be validated. But the transition from what it is now to what it should be comes with such an immense harm — I don't think we can just go and break pretty much every*) single mariadb installation there is. Just to make it clear, I'm not saying we should not do it at all. I'm saying, we need to figure out how to do it without breaking everything. — | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Daniel Lenski [ 2023-06-19 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
But from a user point of view, all of that was clearly not true.
I'd say that is the prudent and correct approach for MariaDB to take. Every MariaDB client→server connection not using server-cert-verification is already broken: even if they think they're "using SSL", their connections can be trivially MITM'ed (or just downgraded to unencrypted ones) by their ISP, cloud provider, 3-letter intelligence agency, etc.
Yes, this is a small step in the right direction, but …
… so this small change towards opportunistic-SSL-by-default is largely ineffectual. It won't protect against the kind of pervasive attackers that everyone has incorporated into their threat model at least since 2013.
Keep in mind that almost all other client/server software that purports to use TLS has consistently made the opposite choice for at least 1 decade: opt for actual security, rather than backwards-compatibility, when a vulnerability is found. MariaDB appears to be far behind the curve in this regard. Why not simply put out very clear documentation with an upcoming MariaDB release that there is going to be substantial backwards-incompatible changes in MariaDB server and client libraries in order to catch up with longstanding best practices for TLS? That documentation can include explaining about how to revert to the old behavior with the new server/client versions, as well as the risks of doing so. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Golubchik [ 2023-06-28 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
What about this approach:
This should cover most use cases:
Basically, this solution relies on the fact that one needs either --ssl-ca or --tls-fp or --ssl-verify-server-cert to make sure the connection is secure. So in all those cases we'll refuse to connect without ssl. Simple --ssl does not guarantee anything, it means the user doesn't care, so we won't require ssl in that case, but we'll issue a warning, telling the user that he should care and how to enable ssl correctly. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Geoff Montee (Inactive) [ 2023-06-28 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hi serg, In my opinion, that plan sounds good. It looks like your proposed implementation covers the same use cases as MySQL's --ssl-mode, but your idea does it by preserving backwards compatibility:
The idea to add a deprecation message for --ssl also sounds good to me. A potential downside is that MySQL's implementation offers more flexibility in some cases. For example, let's say that a DBA has many servers that require TLS with certificate verification, but they also have a handful of other servers in which TLS is not enabled for whatever reason. The DBA might want to add their certificates and keys to their configuration file to save them typing:
With MySQL 8.0, it sounds to me like the DBA would be able to do this *and* still connect to all of the servers: those that require TLS with certificate verification and also those that don't have TLS enabled, since MySQL 8.0's default mode is --ssl-mode=PREFERRED and since the other --ssl* options don't implicitly change the mode anymore in MySQL 8.0. Although, in MySQL 5.7, the other --ssl* options do implicitly change the mode according to the MySQL 5.7 documentation. In contrast, with your proposed implementation, it sounds to me like the DBA would not be able to connect to the servers that don't have TLS enabled, because having the --ssl-ca option in the configuration file would implicitly set behavior equivalent to --ssl-mode=VERIFY_CA. When the DBA tried to connect, the client would require TLS with certificate verification. We could solve this case by treating --ssl* options in configuration files differently than they are treated on the command-line. However, that might break some backward-compatibility. Either way, this case might not be important. Your idea is still a good one. Thanks! | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Golubchik [ 2023-08-30 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
This became obsolete by Within Within |