Red Hat Bugzilla – Bug 541233
CVE-2009-4028 mysql: client SSL certificate verification flaw
Last modified: 2015-02-20 11:28:47 EST
Domas Mituzas reported an absent X.509 certificate verification
check, present in configuration, when MySQL client linked against
OpenSSL toolkit was requested to securely connect to MySQL server,
linked against the yaSSL toolkit. In such situation, X.509 certificates
presented by the "MySQL yaSSL server" were not validated by "MySQL
OpenSSL" client, which could lead to requested security connection
confidentiality, authenticity and integrity break-out.
Upstream bug report:
Further issue exploitation note:
This issue affects only configurations, where MySQL client, as
shipped within Red Hat Enterprise Linux mysql package, was
connecting to external MySQL server linked against the yaSSL
The MySQL servers, as shipped within Red Hat Enterprise Linux
mysql-server package are linked against the OpenSSL toolkit,
and thus not vulnerable to this flaw.
This issue does NOT affect the version of the mysql package, as shipped
with Red Hat Enterprise Linux 3.
This issue affects the versions of the mysql package, as shipped with
Red Hat Enterprise Linux 4 and 5.
Given the fairly suspicious upstream description of this flaw ("OpenSSL clients" vs. "yaSSL servers"), I had a closer look into this. The result of the investigation is that this is not at all specific to "yaSSL servers", but is a flaw in the way MySQL was using OpenSSL library.
MySQL registers a verification callback executed by OpenSSL library during SSL handshake. This callback - vio_verify_callback - turns all peer certificate verification problems on depth 0 into successes, so SSL_connect / SSL_accept / SSL_do_handshake does not return error code when problems are only detected on depth 0. Hence when server presents self-signed certificate, it is always accepted by mysql client.
Problem can be easily reproduced with MySQL server linked against OpenSSL using following settings in my.cnf:
and client connecting as:
mysql -u user dbname --ssl --ssl-ca /dev/null
which is also mentioned as an easy way to make SSL connection "work" in user comments for MySQL documentation:
Note: --ssl-verify-server-cert does not help here, as it only controls whether a connection host name is compared to CommonName in the server certificate. This check is disabled by default and is not implemented in MySQL 4.x versions.
It is also possible to get the same results with CA-signed server certificate, provided that ssl-ca is *not* configured for mysqld (which is not needed unless client certificates are used).
Once ssl-ca is configured for mysqld, this CA certificate will be added to the certificate chain sent to connecting client and will cause depth 1 verification error if incorrect ssl-ca is configured on the client side.
Upstream patch as applied to 4.1-branch does not seem to be sufficient to address these client-side server certificate verification issues, as current 4.x code does not perform any server certificate verification at least as of this commit / bug report:
More importantly, this callback is used on the server side too. MySQL server supports client SSL certificates. It is possible to GRANT permissions based on them, which can be used to create configurations using certificate authentication only (GRANT ... REQUIRE SUBJECT ...), or configurations with multi factor authentication (password + client certificate signed by trusted CA; GRANT ... REQUIRE X509 / ISSUER / SUBJECT ...). Luckily, SSL_get_verify_result is called when checking these ACLs, so client connecting with invalid certificate is rejected. That does not happen in the form of SSL handshake error, but rather client gets "Access denied" MySQL protocol error.
The original report (c#0) is CVE-2009-4028:
The vio_verify_callback function in viosslfactories.c in MySQL 5.0.x
before 5.0.88 and 5.1.x before 5.1.41, when OpenSSL is used, accepts a
value of zero for the depth of X.509 certificates, which allows
man-in-the-middle attackers to spoof arbitrary SSL-based MySQL servers
via a crafted certificate, as demonstrated by a certificate presented
by a server linked against the yaSSL library.
Note that the upstream patch simply removes the special callback and lets openssl do its normal thing. While this is Clearly The Right Thing, I am a bit worried about the idea of just shoving it into an async RHEL update, as it seems entirely likely that it will break some people's self-signed-certificate setups (as per discussion in the upstream bug). Stating that those setups were wrong to begin with may fail to mollify them.
Not sure that we have any good alternative, though.
mysql-5.1.41-2.fc12 has been pushed to the Fedora 12 stable repository. If problems still persist, please make note of it in this bug report.
mysql-5.1.41-2.fc11 has been pushed to the Fedora 11 stable repository. If problems still persist, please make note of it in this bug report.
I face the ERROR 2026 (HY000): SSL connection error again after the upgrading of mysql-5.1.41 to 5.1.41-2, its still exits, but one interesting thing is that when i make a fresh install of mysql-5.1.41-2 on another machine its working fine with SSL, but not successful in upgrade to mysql-5.1.41 to mysql-5.1.41-2, kindly check and test this also.
MySQL SSL error messages are pretty bad, as they don't explain why the issue failed. I'd guess your problem may be due to something wrong in your setup (incorrect ssl-* settings for either client or server, something wrong with certificates), but there's not enough info in your comment to tell. If you have more info to share, please open separate bug report against proper Fedora version. As far as I can see, before 5.1.41-2, 5.1.41 was only available in F13 / Rawhide. Feel free too CC me on the bug, if you create one. Thanks.
Will there be a fix for Red Hat Enterprise Linux 4 & 5?
(In reply to comment #12)
> Will there be a fix for Red Hat Enterprise Linux 4 & 5?
As noted above, MySQL version in Red Hat Enterprise Linux 4 has SSL checking disabled, so the fix for this particular problem does not make a difference. The fix may appear in EL5 updates, though it's not yet decided whether in some asynchronous or scheduled update, given the risks for systems with bad SSL setups.
I'm confused about the test case given in comment #2. mysql seems to be able to connect with the --ssl-ca /dev/null option with or without the patch. Is that expected? What should I do to get different results?
(In reply to comment #15)
> I'm confused about the test case given in comment #2. mysql seems to be able
> to connect with the --ssl-ca /dev/null option with or without the patch. Is
> that expected? What should I do to get different results?
That should be failing. 5.1.41 does. Does it connect even when you try some other valid certificate (e.g. standard CA bundle)?
Oh, never mind, I must've fat-fingered the test somehow. After reinstalling it does work:
[tgl@rh2 x86_64]$ mysql -u root test --ssl --ssl-ca /dev/null
ERROR 2026 (HY000): SSL connection error
Sorry for the noise. I'll have something committed for this soon.
Oh, this is going to be more painful than I realized: now the regression tests fail with 2026 SSL connection error, ie, their setup for SSL testing depends on the "easy shortcut" :-(
No, scratch that, the problem is with the self-signed certs they use for testing:
Not Before: Jan 28 10:55:13 2009 GMT
Not After : Jan 28 10:55:13 2010 GMT
ie, their SSL tests stopped working everywhere, for everybody, about nine hours ago.
Idiots. Didn't they learn from the last time they shipped a test cert with a short lifespan?
Looking back, the "last time" was exactly a year ago --- they replaced a short-lifespan cert with another one. So, assuming they're going to be equally shortsighted this time around, it seems like we ought to generate our own test certs and make our own decision about when they expire.
Can anyone point me to a cookbook procedure for whipping up a CA cert and some server certs signed by it? I can't claim to be familiar enough with SSL to be sure how to do that.
You could try this (completely untested):
(In reply to comment #20)
> Can anyone point me to a cookbook procedure for whipping up a CA cert and some
> server certs signed by it? I can't claim to be familiar enough with SSL to be
> sure how to do that.
Howto pointed out by Vincent is using 'openssl ca', which is little more work to setup properly (directory setup, possible opnessl.cnf changes). Following should be sufficient for testing certificates with little less overhead.
Generate self-signed certificate (can be used for either self-signed server certificates or CA certificate), valid for ~20 years:
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 7300 -key ca.key -out ca.crt
Serial file will be needed later:
echo 00 > ca.srl
Server key and certificate sign request:
openssl genrsa -out server.key 4096
openssl req -new -key server.key -out server.csr
Issue certificate signed by CA:
openssl x509 -req -days 7300 -CA ca.crt -CAkey ca.key -CAserial ca.srl -in server.csr -out server.crt
For the automated test-suite, 'openssl req' calls should get answers piped-in as e.g.:
echo -e "\n\n\n\nserver.host.name\n\n\n\n" | openssl req ...
Thanks guys, I got it working. Back to patching ...
This issue has been addressed in following products:
Red Hat Enterprise Linux 5
Via RHSA-2010:0109 https://rhn.redhat.com/errata/RHSA-2010-0109.html