MySQL SSL Users: BEWARE This Bug

If you’re using MySQL and SSL, you might want to glance over this article and give your setup a quick test.

** Update: If you are looking for “how-to” set up SSL for MySQL (something much clearer than the MySQL manual that also exposes some hidden facts), then please see this article I’ve written here: Setting Up SSL For MySQL **

I’ve uncovered an alarming bug in 5.5 where one could gain access to your MySQL instance just knowing the username and password (not having any SSL certificate, key, etc.)!

Of course, I’ve filed a bug about it here:

http://bugs.mysql.com/bug.php?id=62743

It’s been over 4 days now, and not one comment from the MySQL Bug/Dev Team.

So once again, I feel the need to share this bug with the public, in case you are using SSL with 5.5, and think your connections are secure, or that only users with the certs/key could gain access.

For SSL Users, you’ll already have this set up, but for those who don’t, I’ve simply got mysqld (5.5.15 and 5.5.16 thus far) running with the following options:

ssl-ca	 = "C:/Program Files/MySQL/mysql-5.5.16/certs/ca-cert.pem"
ssl-cert = "C:/Program Files/MySQL/mysql-5.5.16/certs/server-cert.pem"
ssl-key	 = "C:/Program Files/MySQL/mysql-5.5.16/certs/server-key.pem"

In theory, any user connecting should either be specifying the –ssl-ca option, path, and file, or both the –ssl-cert and –ssl-key options.

However, at least in 5.5.15 and 5.5.16 (haven’t tested any others yet), one can connect with *just* the –ssl-key option.

What’s worse, and most important, is that you don’t even have to specify a file here. Just specify some bogus text!

I created 2 users, one local and one remote, using these 2 commands:

GRANT ALL PRIVILEGES ON *.* TO 'ssluser'@'localhost' IDENTIFIED BY 'ssluser' REQUIRE SSL;)
GRANT ALL PRIVILEGES ON *.* TO 'ssluser'@'remote-hostname' IDENTIFIED BY 'ssluser' REQUIRE SSL;

Now, just specify “buggg” for the -ssl-key option (no path, no file, no nothing):

mysql -ussluser -pssluser -P3430 --ssl-key=buggg

Voila!

The user connects as if it were using an SSL connection. All that was needed to connect to this remote host is the username and password.

Check out the output:

Localhost:

C:\Program Files\MySQL\mysql-5.5.16\bin>mysql -ussluser -pssluser -P3430 --ssl-key=buggg
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 5.5.16-log MySQL Community Server (GPL)

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> status
--------------
mysql  Ver 14.14 Distrib 5.5.16, for Win32 (x86)

Connection id:          11
Current database:
Current user:           ssluser@localhost
SSL:                    Cipher in use is DHE-RSA-AES256-SHA
Using delimiter:        ;
Server version:         5.5.16-log MySQL Community Server (GPL)
Protocol version:       10
Connection:             localhost via TCP/IP
Server characterset:    latin1
Db     characterset:    latin1
Client characterset:    cp850
Conn.  characterset:    cp850
TCP port:               3430
Uptime:                 35 min 26 sec

Threads: 1  Questions: 24  Slow queries: 0  Opens: 33  Flush tables: 1  Open tables: 0
Queries per second avg: 0.011
--------------

Remote Host:

C:\Documents and Settings>mysql -ussluser -pssluser -h192.168.1.100 -P3430 --ssl-key=buggg
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.5.16-log MySQL Community Server (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> status
--------------
mysql  Ver 14.12 Distrib 5.0.70, for Win32 (ia32)

Connection id:          6
Current database:
Current user:           ssluser@HOST-LAPTOP
SSL:                    Cipher in use is DHE-RSA-AES256-SHA
Using delimiter:        ;
Server version:         5.5.16-log MySQL Community Server (GPL)
Protocol version:       10
Connection:             192.168.1.100 via TCP/IP
Server characterset:    latin1
Db     characterset:    latin1
Client characterset:    latin1
Conn.  characterset:    latin1
TCP port:               3430
Uptime:                 13 min 13 sec

Threads: 2  Questions: 14  Slow queries: 0  Opens: 33  Flush tables: 1 Open tab
les: 26  Queries per second avg: 0.017
--------------

Again, I have no idea how many versions are affected by this yet. I’ve only tested 5.5.15 and 5.5.16 (seen on both Windows and Linux, as well).

In fact, that’s all I thought I would have needed to test, as I thought MySQL would have been all over this bug. But since there’s been no word from them about it, I feel it’s my duty to let the community know about this bug until it gets fixed.

(And I even wonder if the above is secure or not. I mean, it “says” the cipher is in use, but since I didn’t specify a ssl cert or key, how can I be certain this is secure.)

Tags: , , , , , , , , , , , , , , , , , , ,

16 Responses to “MySQL SSL Users: BEWARE This Bug”

  1. You can test by using tcpdump to sniff the traffic and see if it’s going by encrypted or unencrypted:

    http://forge.mysql.com/tools/tool.php?id=15

    According to the manual, REQUIRE SSL means that the ssl-key is optional. ssl-ca is not, though — you might want to make sure you aren’t accidentally connected to an unsecure user — try SELECT USER(), CURRENT_USER(); once you are logged in to see what the result is, and then try SELECT user,host,ssl_type FROM mysql.user WHERE user=’ssluser’; to make sure there is not an unsecure user — my guess here is that it’s ignoring the ssl-key.

    Here’s the source — http://dev.mysql.com/doc/refman/5.5/en/grant.html

    “The REQUIRE SSL option tells the server to permit only SSL-encrypted connections for the account.

    GRANT ALL PRIVILEGES ON test.* TO ‘root’@'localhost’
    IDENTIFIED BY ‘goodsecret’ REQUIRE SSL;

    To connect, the client must specify the –ssl-ca option, and may additionally specify the –ssl-key and –ssl-cert options.”

    If you want MySQL to validate a certificate, you have to use REQUIRE X509:

    “REQUIRE X509 means that the client must have a valid certificate but that the exact certificate, issuer, and subject do not matter.”


    And finally if you want even more security:

    “REQUIRE ISSUER ‘issuer’ places the restriction on connection attempts that the client must present a valid X509 certificate issued by CA ‘issuer’. ”

    I’m interested in seeing the result. I think even if it’s a mistake you made, though, the bugs team should have responded by now.

  2. Davi Arnaut says:

    A key without a certificate means nothing, so it gets ignored. Otherwise, it’s still possible to establish a SSL connection. Perhaps what you want is “REQUIRE SUBJECT” or some of the other REQUIRE variants.

  3. chris says:

    Thank you for your comments. Let me post some replies ..

    For one, an unsecure user (even with this bug) would not be able to connect. It would be properly ignored (and it is). You must be using an SSL user account.

    Secondly, the “current_user()” output is already present in the “status” output. It shows the “Current user” is “ssluser@localhost” and “ssluser@HOST-LAPTOP”.

    But for completeness, here are the outputs:

    C:\Program Files\MySQL\mysql-5.5.16\bin>mysql -ussluser -pssluser -P3430 --ssl-key=blah
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 2
    Server version: 5.5.16-log MySQL Community Server (GPL)
    ...
    mysql> status;
    --------------
    mysql  Ver 14.14 Distrib 5.5.16, for Win32 (x86)
    
    Connection id:          2
    Current database:
    Current user:           ssluser@localhost
    SSL:                    Cipher in use is DHE-RSA-AES256-SHA
    Using delimiter:        ;
    Server version:         5.5.16-log MySQL Community Server (GPL)
    ...
    --------------
    
    mysql> select user(), current_user();
    +-------------------+-------------------+
    | user()            | current_user()    |
    +-------------------+-------------------+
    | ssluser@localhost | ssluser@localhost |
    +-------------------+-------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT user,host,ssl_type FROM mysql.user;
    +---------+-------------+----------+
    | user    | host        | ssl_type |
    +---------+-------------+----------+
    | root    | localhost   |          |
    | root    | 127.0.0.1   |          |
    | root    | ::1         |          |
    | ssluser | host-laptop | ANY      |
    | ssluser | localhost   | ANY      |
    +---------+-------------+----------+
    5 rows in set (0.00 sec)

    Above, you can see the ‘root’ user is not an SSL user, whereas the ‘ssluser’ is.

  4. Davi Arnaut says:

    Chris,

    I’m not understanding what is the issue. The REQUIRE SSL option tells the server to permit only SSL-encrypted connections for the account. A client certificate/key is not required to establish a SSL connection.

  5. OK, so the bug is that REQUIRE SSL isn’t actually enforcing the encryption. The ssl-key is very likely being ignored.

    Have you tried sniffing traffic to see if it’s encrypted? (though I agree, the connection should be rejected if you’re not using a certificate).

    This is a regression, though (or perhaps is only on your OS) — I set up SSL for a client running 5.1 and tested that it rejected non-ssl connections…then again, I didn’t try with a random optional option like ssl-key.

  6. chris says:

    @Davi,

    The manual says this:

    The REQUIRE SSL option tells the server to permit only SSL-encrypted connections for the account.
    ...
    To connect, the client must specify the --ssl-ca option, and may additionally specify the --ssl-key and --ssl-cert options.

    I am connecting without specifying –ssl-ca *and* it still indicates that I am connected via ssl (and mentioned the cipher).

    I think the bug is quite clear.

  7. Davi Arnaut says:

    > Have you tried sniffing traffic to see if it’s encrypted? (though I agree,
    > the connection should be rejected if you’re not using a certificate).

    I’m confused, a client-side certificate should not required for establishing a SSL connection. Usually, a client certificate is only used when the server wants to verify who is the client. The most common case is that the server sends the client a certificate so the client can verify who the server is.

  8. Davi Arnaut says:

    > I am connecting without specifying –ssl-ca *and* it still indicates that I
    > am connected via ssl (and mentioned the cipher).

    A client-side certificate is not required for establishing a SSL connection.

    See http://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_handshake_in_detail

    > I think the bug is quite clear.

    Sorry, still not clear to me.

  9. Davi Arnaut says:

    “As of MySQL 5.0.40, if you use SSL when establishing a client connection, you can tell the client not to authenticate the server certificate by specifying neither –ssl-ca nor –ssl-capath. The server still verifies the client according to any applicable requirements established using GRANT statements for the client, and it still uses any –ssl-ca/–ssl-capath values that were passed to server at startup time.”

  10. chris says:

    You keep saying no options even need specified. Really, if that’s the case, then why must I?

    Test with no options, as you’ve suggested:

    C:\Program Files\MySQL\mysql-5.5.16\bin>mysql -ussluser -pssluser -P3430
    ERROR 1045 (28000): Access denied for user 'ssluser'@'localhost' (using password: YES)

    Fails!

    Now add some bogus crap (this works, just as the bug report states):

    C:\Program Files\MySQL\mysql-5.5.16\bin>mysql -ussluser -pssluser -P3430 --ssl-key=crap
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 2
    Server version: 5.5.16-log MySQL Community Server (GPL)
    
    Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    mysql> status
    --------------
    mysql  Ver 14.14 Distrib 5.5.16, for Win32 (x86)
    
    Connection id:          4
    Current database:
    Current user:           ssluser@localhost
    SSL:                    Cipher in use is DHE-RSA-AES256-SHA
    Using delimiter:        ;
    Server version:         5.5.16-log MySQL Community Server (GPL)
    ...

    How is that not a bug! Get real.

  11. Davi Arnaut says:

    –ssl-key implies –ssl. The former gets ignored (reasons outlined in the bug report), but not the latter. It is the same as the command mysql-ussluser -pssluser -P3430 –ssl

    > How is that not a bug! Get real.

    There might be a bug somewhere that I might have missed, but what I have seen so far is that the MySQL SSL options are utterly confusing to users.

  12. What SSL lib is in use?

  13. chris says:

    @Davi:

    I appreciate your comments and insight, and I agree, the manual is very lacking (and incorrect) in the SSL department. It needs a complete overhaul, imho.

    However, I disagree with one of your major points.

    You said this (first command was mine):

    > > C:\Program Files\MySQL\mysql-5.5.16\bin>mysql -ussluser -pssluser -P3430 –ssl-key=crap
    >
    > Although –ssl-key is ignored, the option implies –ssl as documented. This is equivalent to:
    >
    > mysql -ussluser -pssluser -P3430 –ssl

    Well, I thought I’d spend the 3 minutes it took to *test* this out, and it is not the same, because it *does not* work. See below, where I tried with –ssl, –ssl=1, and then you see it works with –ssl-key=1234:

    C:\Program Files\MySQL\mysql-5.5.16\bin>mysql -ussluser -pssluser -P3430 --ssl
    ERROR 1045 (28000): Access denied for user 'ssluser'@'localhost' (using password: YES)
    
    C:\Program Files\MySQL\mysql-5.5.16\bin>mysql -ussluser -pssluser -P3430 --ssl=1
    ERROR 1045 (28000): Access denied for user 'ssluser'@'localhost' (using password: YES)
    
    C:\Program Files\MySQL\mysql-5.5.16\bin>mysql -ussluser -pssluser -P3430 --ssl-key=1234
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 4
    Server version: 5.5.16-log MySQL Community Server (GPL)
    
    Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    mysql> exit
    Bye

    Somewhere there is a bug, and not just a documentation bug.

  14. Davi Arnaut says:

    > Somewhere there is a bug, and not just a documentation bug.

    MySQL client code:

    if (opt_use_ssl)
    mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
    opt_ssl_capath, opt_ssl_cipher);

    MySQL client library code:

    #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
    if (mysql->options.ssl_key || mysql->options.ssl_cert ||
    mysql->options.ssl_ca || mysql->options.ssl_capath ||
    mysql->options.ssl_cipher)
    mysql->options.use_ssl= 1;
    if (mysql->options.use_ssl)
    mysql->client_flag|= CLIENT_SSL;
    #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY*/

    So, in the clients, –ssl only specifies that the SSL options should be set (using mysql_ssl_set). Whether SSL is really used only happens if one of the -ssl-* options is set.

    Whatever garbage is fed to –ssl-key makes “use SSL” be activated even though the key is ignored.

  15. XL says:

    Chris,

    this is not a bug. It would only be a bug if the client would be lying about the encryption. I doubt that it does. Sniff the network to find this out.

    The point is, that REQUIRE SSL does NOT require the client to have a certificate. It requires a successful SSL handshake such that the connection is encrypted. Depending on the SSL lib in use, this will not even require a CA certificate in the client. Especially this is the case with openssl and a self-signed server certificate. There is however a logic bug in the client option parsing, such that –ssl alone is not enough, one also have to set one of the other ssl options, even when it is not used.

    If you want to enforce the presence of a certificate in the client, then use REQUIRE X509. Probably you would rather REQUIRE a certain ISSUER or SUBJECT. See http://dev.mysql.com/doc/refman/5.1/en/grant.html for a summary of SSL options.

    XL

  16. chris says:

    From the good learned from this post/discussion, I’ve written an in-depth, yet concise “how-to” on setting up SSL for MySQL:

    http://www.chriscalender.com/?p=448


Period Panties by Period Panteez Menstrual Underwear Menstruation PMS Panty