Bug 1029396 - (CVE-2017-3305) VUL-0: CVE-2017-3305: mysql: MySQL client send authentication request unencrypted even if SSL is REQUIRED (RIDDDLE.LINK)
(CVE-2017-3305)
VUL-0: CVE-2017-3305: mysql: MySQL client send authentication request unencry...
Status: RESOLVED FIXED
Classification: Novell Products
Product: SUSE Security Incidents
Classification: Novell Products
Component: Incidents
unspecified
Other Other
: P3 - Medium : Normal
: ---
Assigned To: Security Team bot
Security Team bot
CVSSv2:SUSE:CVE-2017-3305:5.1:(AV:N/A...
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2017-03-14 19:20 UTC by Victor Pereira
Modified: 2019-08-16 15:25 UTC (History)
2 users (show)

See Also:
Found By: ---
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Victor Pereira 2017-03-14 19:20:31 UTC
Hi! I discovered SSL related security problem in MySQL 5.5 and 5.6 
client libraries. Public disclosure will be at 17th March.

I'm resending details about vulnerability which I sent to Debian 
security team. So you would have some time to prepare if you need it 
before public disclosure.

I have successfully implemented MITM script to verify that attack is 
really possible.

----------  Forwarded Message  ----------

Hi!

I'm observing strange behaviour in MySQL client. When I specify option 
that SSL/TLS encryption layer is required and target MySQL server does 
not support TLS then MySQL client fallbacks to unencrypted plain text 
protocol and starts authentication session via it.

MySQL client *after* successful authentication checks if SSL/TLS layer 
is required and if server have not support it after then it close 
connection with fatal error.

This problem is present in last 5.5 (5.5.54) and also 5.6 (5.6.35) 
versions. But not in last 5.7 (which seems to be fixed).

You can easily verify it by starting non-SSL MySQL server on localhost, 
start wireshark and run command:

$ mysql --ssl-mode=REQUIRED -u root -ppassword -h 127.0.0.1

Then you can that authentication request is really unencrypted and sent 
data are in format described at:

https://dev.mysql.com/doc/internals/en/secure-password-authentication.html

Active MITM attacker can downgrade SSL/TLS to plain text, forward nonce 
from server back to client. MITM attacker receive from client login data 
(for server nonce), send it to server and should be authenticated. 
Client just detect that connection is not SSL/TLS and throws error. 
Attacker in that time is already connected to MySQL server.

Note that this problem is present in libmysqlclient.so (in 5.5 and 5.6) 
versions, so any application which uses it is probably vulnerable to 
this attack (not only "mysql").

And if you look at documentation for MySQL 5.5 and MySQL 5.6 you can see 
that *suggested* option how to enforce SSL/TLS is by first calling 
mysql_real_connect() and then verify that SSL/TLS was really established 
by mysql_get_ssl_cipher(). Problem is that mysql_real_connect() takes 
arguments "user" and "passwd" and check for SSL/TLS is *after* that.

https://dev.mysql.com/doc/refman/5.5/en/mysql-ssl-set.html
https://dev.mysql.com/doc/refman/5.6/en/mysql-ssl-set.html

So probably other applications which follows MySQL documentation are 
vulnerable to this attack too.

-- 
Pali Rohár
pali.rohar@gmail.com
Comment 2 Marcus Meissner 2017-03-20 13:30:40 UTC
is public
Comment 3 Marcus Meissner 2017-03-20 13:32:25 UTC
  Technical section

   DISCLAIMER: THE FOLLOWING SECTION IS UNIMPORTANT FOR THE MAJORITY OF
   PEOPLE AS IT IS NOT USEFUL FOR THE MEDIA OR ANY OTHER NEWS RELATED
   WEBSITES DUE TO BORING TECHNICAL INFORMATION AND DETAILS. IT IS PROVIDED
   "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
   NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
   PURPOSE AND NONINFRINGEMENT. BY READING THE FOLLOWING SECTION YOU AGREE TO
   NOT USE IT IN THE MICROWAVE. THE ENTIRE RISK AS TO THE QUALITY OF THE
   FOLLOWING SECTION IS WITH YOU. YOU ASSUME THE COST OF ALL NECESSARY
   SERVICING, REPAIR OR CORRECTION. ANTE USUM AGITETUR!

    What is the real problem?

   MySQL client library doesn't verify if security of the connection matches
   the parameters specified by the user before starting negotiation of the
   authentication with MySQL server. After the BACKRONYM vulnerability had
   been discovered, it was fixed by Oracle in MySQL 5.7. Security update for
   the stable MySQL 5.5.49 and 5.6.30 versions consisted of adding a
   verification of security parameters after the authentication process was
   finished. Since, it is done after the authentication man riddle in the
   middle attack together with SSL-downgrade attack can be used by the
   attacker to steal login data for immediate authentication and login to the
   MySQL server. Ridiculous part is that MySQL client doesn't report any SSL
   related error when MySQL server declines to authenticate a user and
   instead reports unencrypted error message send by the server. Furthermore,
   the error message is controlled by the attacker, when the riddle in the
   middle attack is active.

    How can the attack look like?

   The attacker needs to sit with riddle in the middle of the MySQL client
   and MySQL server and needs to have the ability to modify MySQL protocol
   communication. Due to (not fully) secure password authentication scheme
   which MySQL protocol uses, attacker can catch the server nonce from
   properly secured SSL connection with MySQL server and then forward it to
   the client via non-secure plain text connection. In this phase, the client
   doesn't do any verification of security parameters and it also doesn't
   verify if the other side that sent the the nonce really knows the password
   (or have ability to verify if supplied data are correct). Thus, the client
   doesn't report any problem that SSL connection isn't used and it generates
   authentication response. The response is sent back to other side (to the
   attacker) without any complains via insecure plain text mode. The attacker
   then finds in the riddle authentication response, sends it to the real
   MySQL server and voila attacker has access to MySQL server database.
   Afterwards, attacker sends some error message to the client and the client
   propagates it to the user. The error message can contain arbitrary string
   and the client doesn't show any problems related to disabled SSL mode even
   when SSL mode was explicitly set to required. The user's password isn't
   disclosed as a result of the attack. The attacker can authenticate to
   MySQL server without the password only once as the server nonce is always
   (or should be) different. If authentication scheme were more robust (e.g.
   SCRAM), then this attack wouldn't be possible. It remains to be seen
   whether Oracle will be willing to switch authentication scheme to
   something more robust after this vulnerability was discovered and
   reported.

    Which versions of the libraries are affected?

   All versions of MySQL 5.5 and 5.6 client libraries (at the time of writing
   of this article). Note that MariaDB client libraries aren't affected by
   this vulnerability as MariaDB developers fixed BACKRONYM properly and
   verification of the security parameters is done before sending user
   credentials. Furthermore, all the programs which use MySQL or MariaDB
   client library incorrectly are also affected.

    How do I verify if a program which uses MySQL/MariaDB is affected?

   Oracle in MySQL 5.5 documentation demonstrates how to enforce SSL
   encryption via function mysql_connect_ssl_check(). The code example in the
   documentation is incorrect as it introduces a vulnerability to your
   program! In the example, the check whether SSL was established is done
   after starting the authentication process. If your MySQL program uses the
   recommendation or directly the code example provided by Oracle, then your
   program is affected by Riddle vulnerability independently of MySQL client
   library. Therefore, fixing MySQL client library isn't enough and MySQL
   program must be fixed too.

    How do I check if my system is affected by this defect?

   You are affected if you are using MySQL client in any version 5.5 or 5.6
   or you are using affected program as described above and you depend on SSL
   encryption over untrusted network where attacker can apply riddle in the
   middle.

    How can I mitigate this problem?

   You have couple of options. The best way would be to stop using the
   affected libraries, either by upgrading your MySQL client to version 5.7
   or by switching from MySQL to MariaDB client. You can also apply MariaDB
   patch for the BACKRONYM vulnerability to your MySQL client. Note that
   MySQL client is backward compatible and version 5.7 can connect to MySQL
   server 5.6 or 5.5 without any problems. So, you just need to upgrade the
   client without touching the server part. Another option is to stop
   relaying on SSL enforced encryption by MySQL and create your own correctly
   encrypted secure tunnel. You can use e.g. socat program which can create a
   bidirectional SSL tunnel or use any other secure tunnel based on SSH, VPN
   or IPSec. The last option is to apply ostrich effect and wait until Oracle
   fixes MySQL client libraries and starts distributing them to you. In that
   case, you should expect that you could be victim of a attack.

    How do I use SSL encryption properly?

   SSL (resp. TLS, as SSL v2/v3 is already broken but name SSL is commonly
   used for TLS protocol) implementation or protocol itself isn't affected by
   this vulnerability. The whole problem is how MySQL client uses SSL
   encryption. Men in the middle attack is very common for SSL and to prevent
   it, client must verify if SSL tunnel was correctly established with
   correct server and not with some attacker's server. It means that client
   must verify SSL certificate announced by the server and also that the
   certificate is really owned by the server. If the connection to MySQL
   server is SSL encrypted but MySQL client doesn't verify certificate
   (correctly!), then man in the middle attack is still possible and
   downgrade attack is needed. The Riddle vulnerability shows that MySQL
   client does whole verification at wrong a time -- after the authentication
   was finished. Not before. So, enforcing SSL mode isn't enough, you also
   need to tell MySQL client how it must verify server's SSL certificate.
   Either that it is signed by really trusted certificate authority or that
   it matches server's certificate directly.

    Are there some implementations of riddle in the middle already?

   Yes, there is my proof of concept riddle.pl script written in Perl. It
   starts riddle on localhost:3307 and expects that MySQL server is running
   on localhost:3306. If you connect with affected client to localhost:3307,
   then riddle will catch and steal authentication information, connects to
   real MySQL server on localhost:3306 and executes SQL for returning number
   of all tables.

      Example which expects that MySQL server is already running on localhost:

   Start riddle in the middle server:

 $ perl riddle.pl

   Connect with your MySQL client to riddle, replace user and password:

 $ mysql --ssl-mode=REQUIRED -h 127.0.0.1 -P 3307 -u user -ppassword

   If you provided correct user and password, then riddle connects to the
   server, executes SQL and writes output:

 SELECT COUNT(*) FROM information_schema.TABLES --> 121

   MySQL client just receives a nice error message sent by riddle:

 ERROR 1045 (28000): Access denied: MITM attack

    Timeline

     * 2017-02-01 - me - Discovered the vulnerability
     * 2017-02-04 - me - Contacted Debian Security team because defect was
       present in Debian's libmysqlclient.so library
     * 2017-02-06 - me - Provided POC perl script
     * 2017-02-06 - Debian & Oracle - Oracle person CCed by Debian Security
       team passed the information on upstream
     * 2017-02-10 - me - Requested information about the state and progress
       of the reported vulnerability
     * 2017-02-16 - Debian - Asked about the state again, since there was no
       answer from Oracle
     * 2017-02-23 - me - Issued another request about the current state and
       announced date of public disclosure to 2017-02-28 due to Oracle's
       inactivity
     * 2017-02-23 - Debian - Suggested to disclose the vulnerability as
       upstream has failed to respond
     * 2017-02-24 - Debian - Contacted Oracle team again
     * 2017-02-25 - Oracle - Answered that they were not aware of this issue,
       even though it was already passed on to them on 2017-02-06 and I
       inquired 4 times about the progress
     * 2017-02-27 - Oracle - Answered that they will provide response quickly
     * 2017-02-28 - me - Requested the current state again as Oracle hasn't
       respond yet
     * 2017-02-28 - Oracle - Answered that will have response shortly
     * 2017-02-28 - me - Reminded them that it was the day of public
       disclosure and offered them postponing the disclosure for a few days
     * 2017-02-28 - Oracle - Accepted an offer to postpone the disclosure
       date to the end of week
     * 2017-03-01 - me - Requested the state of the reported vulnerability
       again because Oracle have not provided any information of progress yet
       (after month!)
     * 2017-03-02 - Oracle - Sent information (for the first time) that they
       were actively working on this issue and asked me to keep it
       confidential until the end of April
     * 2017-03-02 - me - Rejected postponing disclosure date for another two
       months because one month should have been enough to fix the issue and
       users should have been informed about this vulnerability ASAP
     * 2017-03-02 - Oracle - Informed me that it is hard to fix the reported
       issue and requested everybody involved to keep this issue confidential
     * 2017-03-03 - me - Repeated rejection of postponing the disclosure date
       for another two months and offered them postponing the disclosure date
       for one week
     * 2017-03-03 - Oracle - Hasn't stated if they wanted to postpone the
       disclosure, but offered inclusion of my name into a credit section if
       I kept the issue confidential
     * 2017-03-11 - me - Announced to Oracle, Debian Security team, Red Hat
       Security team and SUSE Security team that final public disclosure is
       2017-03-17 (no more postponing)
     * 2017-03-17 - me - Announced the vulnerability to the oss-sec mailing
       list

   As you can see, communication with Oracle is very hard. For ordinary
   people without a big company standing behind them, it probably doesn't
   make any sense filing reports of security vulnerabilities. After one
   month, Oracle have done absolutely nothing. They even wanted to postpone
   the disclosure date for another two months as they are probably
   incompetent to handle the security issues in their products. The only
   thing which Oracle offered as a reward if I do not disclose this issue was
   an inclusion of my name to some Oracle credit section. It is probably the
   last thing which would a developer or a security expert want to see.

   Conclusion: Reporting bugs to Oracle is useless (even those which are
   security related) if you are not a Oracle customer. They can perfectly
   ignore any reports and they would be very happy if nobody knew about it so
   they don't have to fix the bugs. It looks like immediate public disclosure
   is the best responsible solution for the users as it is the only way how
   to protect them and let them know immediately what should be done if they
   are affected.

    Contact

   Email address: middle at riddle dot link

    References

     * Perl script riddle.pl - http://riddle.link/riddle.pl
     * CVE-2017-3305 -
       https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-3305
     * BACKRONYM - http://backronym.fail/
     * MySQL 5.5.49 release notes -
       https://dev.mysql.com/doc/relnotes/mysql/5.5/en/news-5-5-49.html#mysqld-5-5-49-security
     * MySQL 5.6.30 release notes -
       https://dev.mysql.com/doc/relnotes/mysql/5.6/en/news-5-6-30.html#mysqld-5-6-30-security
     * MySQL Secure Password Authentication -
       https://dev.mysql.com/doc/internals/en/secure-password-authentication.html
     * MySQL mysql_connect_ssl_check() function -
       https://dev.mysql.com/doc/refman/5.5/en/mysql-ssl-set.html
     * SCRAM -
       https://en.wikipedia.org/wiki/Salted_Challenge_Response_Authentication_Mechanism
Comment 4 Kristyna Streitova 2017-03-21 12:20:59 UTC
Few important highlights:

(In reply to Marcus Meissner from comment #3)
>    All versions of MySQL 5.5 and 5.6 client libraries (at the time of writing
>    of this article). Note that MariaDB client libraries aren't affected by
>    this vulnerability... 

MariaDB is not affected. Only MySQL 5.5 and 5.6 is.

>    Furthermore, all the programs which use MySQL or MariaDB
>    client library incorrectly are also affected.

An important word here is _incorrectly_. Libmysqlclient is not affected per se as changes that introduced this issue were made only for mysql clients shipped with MySQL. The problem is rather in the documentation that guided users to implement the same approach in their applications:

>    Oracle in MySQL 5.5 documentation demonstrates how to enforce SSL
>    encryption via function mysql_connect_ssl_check(). The code example in the
>    documentation is incorrect as it introduces a vulnerability to your
>    program!

-----

According to the Oracle mysql-ssl-set() documentation (see a difference between the old [1] and the new [2] version of the section "Enforcing an Encrypted Connection"), they changed their mind about a backporting  MYSQL_OPT_SSL_MODE option that "would break binary compatibility with previous library versions" and backported it for MySQL 5.5.55 [2] and MySQL 5.6.36 [3].

<cite>[2]
In MySQL 5.5.55, the MYSQL_OPT_SSL_MODE option for mysql_options() was backported from MySQL 5.7 to MySQL 5.5. A call to mysql_options() to set MYSQL_OPT_SSL_MODE option to value of SSL_MODE_REQUIRED suffices to cause mysql_real_connect() to fail if the connection is not encrypted. mysql_get_ssl_cipher() can still be called after connecting, although it is not necessary to do so.
</cite>

They also added an additional step between mysql_ssl_set() call and mysql_real_connect() call. It's an mysql_options() call with passing the MYSQL_OPT_SSL_MODE option. 

In the light of this, it seems that this issue is fixed in these versions. However, it's not released yet. The next Oracle Critical Patch Update is planned for 18 April 2017 [4].

Unfortunately, we can't cherrypick this bugfix now as for some reason the last change in mysql-server GitHub repository [5] was done in November (they probably use private repo?).


References:
----------
Vulnerability name: The Riddle 
Webpage: http://riddle.link/
Debian: https://security-tracker.debian.org/tracker/CVE-2017-3305
Red Hat: https://bugzilla.redhat.com/show_bug.cgi?id=1431690

[1] https://web.archive.org/web/20161219180824/https://dev.mysql.com/doc/refman/5.5/en/mysql-ssl-set.html
[2] https://dev.mysql.com/doc/refman/5.5/en/mysql-ssl-set.html
[3] https://dev.mysql.com/doc/refman/5.6/en/mysql-ssl-set.html
[4] https://www.oracle.com/technetwork/topics/security/alerts-086861.html
[5] https://github.com/mysql/mysql-server/commits/5.5
Comment 5 Kristyna Streitova 2017-04-19 12:18:32 UTC
MySQL
-----

- this CVE-2017-3305 was fixed within Oracle CPU Advisory - April 2017 [1] in: 
  * MySQL 5.5.55
  * MySQL 5.6.36
  * (MySQL 5.7 is not affected)


[1] http://www.oracle.com/technetwork/security-advisory/cpuapr2017-3236618.html#AppendixMSQL
Comment 7 Bernhard Wiedemann 2017-04-25 12:02:28 UTC
This is an autogenerated message for OBS integration:
This bug (1029396) was mentioned in
https://build.opensuse.org/request/show/490980 42.1+42.2 / mysql-community-server
Comment 8 Kristyna Streitova 2017-04-26 10:43:02 UTC
MariaDB:
--------
- not affected

MySQL:
------
|     Codestream     | Request |
|--------------------|---------|
| SLE11SP3           |  131626 |
| openSUSE:Factory   |  490949 |
| openSUSE:Leap:42.1 |  490980 |
| openSUSE:Leap:42.2 |  490980 |


We are done here. I'm reassigning it back to the security team.
Comment 9 Swamp Workflow Management 2017-04-28 19:14:39 UTC
SUSE-SU-2017:1137-1: An update that fixes 13 vulnerabilities is now available.

Category: security (important)
Bug References: 1020976,1022428,1029014,1029396,1034850
CVE References: CVE-2016-5483,CVE-2017-3302,CVE-2017-3305,CVE-2017-3308,CVE-2017-3309,CVE-2017-3329,CVE-2017-3453,CVE-2017-3456,CVE-2017-3461,CVE-2017-3462,CVE-2017-3463,CVE-2017-3464,CVE-2017-3600
Sources used:
SUSE Linux Enterprise Software Development Kit 11-SP4 (src):    mysql-5.5.55-0.38.1
SUSE Linux Enterprise Server 11-SP4 (src):    mysql-5.5.55-0.38.1
SUSE Linux Enterprise Debuginfo 11-SP4 (src):    mysql-5.5.55-0.38.1
Comment 10 Swamp Workflow Management 2017-05-08 16:19:20 UTC
openSUSE-SU-2017:1209-1: An update that fixes 16 vulnerabilities is now available.

Category: security (important)
Bug References: 1020976,1022428,1029014,1029396,1034850,889126
CVE References: CVE-2016-5483,CVE-2017-3302,CVE-2017-3305,CVE-2017-3308,CVE-2017-3309,CVE-2017-3329,CVE-2017-3450,CVE-2017-3452,CVE-2017-3453,CVE-2017-3456,CVE-2017-3461,CVE-2017-3462,CVE-2017-3463,CVE-2017-3464,CVE-2017-3599,CVE-2017-3600
Sources used:
openSUSE Leap 42.2 (src):    mysql-community-server-5.6.36-24.3.3
openSUSE Leap 42.1 (src):    mysql-community-server-5.6.36-25.3
Comment 11 Victor Pereira 2017-09-20 07:58:58 UTC
all fixed and released