Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Mon, 12 Jun 2017 23:47:54 +0200
From: Pali Rohár <pali.rohar@...il.com>
To: oss-security@...ts.openwall.com,
 security@...iadb.org,
 secalert_us@...cle.com,
 security@...cona.com,
 Andrea Barisani <andrea@...ersepath.com>,
 Michiel Beijen <michiel.beijen@...il.com>,
 Alceu Rodrigues de Freitas Junior <glasswalk3r@...oo.com.br>
Subject: Re: MySQL - use-after-free after mysql_stmt_close()

Hello!

Any idea how to handle this particular problem?

On Thursday 08 June 2017 23:49:03 Pali Rohár wrote:
> Hello!
> 
> MySQL applications written according to Oracle's MySQL documentation
> & examples for mysql_stmt_close() function call are vulnerable to
> use- after-free defect.
> 
> In mysql_stmt_close() documentation [1] for return value is written:
> "Zero for success. Nonzero if an error occurred." And there are
> defined two errors: CR_SERVER_GONE_ERROR CR_UNKNOWN_ERROR. From
> other parts of documentation can be understood that error messages
> for statements could be obtained by mysql_stmt_error() function [2].
> 
> Whole example of usage is written in mysql_stmt_execute() function
> [3]. The relevant part for mysql_stmt_close() is at the end of
> example:
> 
> /* Close the statement */
> if (mysql_stmt_close(stmt))
> {
>   fprintf(stderr, " failed while closing the statement\n");
>   fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
>   exit(0);
> }
> 
> And here is a problem, use-after-free defect. Current implementation
> of mysql_stmt_close() function unconditionally free passed statement
> structure and therefore following mysql_stmt_error() call is
> defective to use-after-free.
> 
> Relevant part of implementation of mysql_stmt_close() function is:
> 
> my_bool mysql_stmt_close(MYSQL_STMT *stmt)
> {
>   int rc=0;
> ...
>   if ((rc= stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt)))
>     set_stmt_errmsg(stmt, &mysql->net);
> ...
>   my_free(stmt);
>   return rc;
> }
> 
> As you can see it stores real error message into stmt structure, but
> at the end it is freed. Which means error message is no longer
> available and caller is not able to read it (even via
> mysql_stmt_error() call).
> 
> As such defective code is in example of the usage, probably couple of
> MySQL applications written according to that defective documentations
> are affected to this issue.
> 
> There is reported real bug for MySQL DBI driver that is affected by
> this issue [4]. Reporter probably compiled MySQL library or driver
> itself with some compiler options which could detect buffer
> overflows and uncovered this issue.
> 
> 
> In April 17 I reported this issue to oCERT team and it was forwarded
> to MySQL, MariaDB and Percona security teams.
> 
> MariaDB team answered that this is problem in Oracle & MySQL and
> their documentation as MariaDB do not have such vulnerable example
> in their documentation.
> 
> Oracle team was unwilling to tell anything, provide any information
> how to handle such issue or what to do, therefore with suggestion
> from oCERT I decided to make this report public and open public
> discussion for other people on oss-security list how to handle this
> problem.
> 
> 
> As Oracle fully ignored this problem and have not stated if problem
> is in documentation, implementation or both, I see probably 3
> different solutions:
> 
> 1) Documentation with examples is correct and this is how it should
> be used. What is wrong is implementation.
> 
> It would mean that function mysql_stmt_error() and mysql_stmt_errno()
> needs to specially handle statement pointers which were already freed
> by mysql_stmt_close(). This can be done e.g. by storing hash table
> of pointers and assigning for them last received error.
> 
> Or clarifying that mysql_stmt_close() does not always free passed
> memory. Because from current description in documentation it is not
> fully unambiguous what happen if function fails.
> 
> In this case implementation of mysql_stmt_close(), mysql_stmt_error()
> and mysql_stmt_errno() are vulnerable to use-after-free defect and
> needs to be fixed. And it should be assigned CVE for MySQL for this
> problem.
> 
> 2) Implementation is correct, documentation is wrong.
> 
> Documentation needs to be fixed to properly describe how are those
> functions implemented. Important note must be that if function
> mysql_stmt_close() fails it is not possible to take error code via
> mysql_stmt_error() or mysql_stmt_errno(). Also examples needs to be
> fixed.
> 
> And then all MySQL applications which were written according to wrong
> documentation needs to be fixed and for each one needs to be assigned
> CVE. Number of those applications is unknown, to get it first every
> application which uses libmysqlclient.so needs to be checked and
> verified. What we know now is that MySQL Perl DBI is affected.
> 
> 3) Documentation is wrong, but implementation of mysql_stmt_close()
> is not-so-correct.
> 
> Which would mean that return value of mysql_stmt_close() is fully
> meaningless as there is no way to recover from bad state. Currently
> mysql_stmt_close() unconditionally free memory for statement, so no
> recover is possible.
> 
> There are two options what can be done:
> 
> * Always return value zero which means no error occurred. This
> basically mitigate use-after-free vulnerability in Oracle's
> documentation and also all applications which were written according
> to documentation.
> 
> * When error occurred, do not free memory of passed structure. This
> would mean that following mysql_stmt_error() call would not be
> affected by use-after-free anymore.
> 
> 
> As Oracle ignored this security related problem (***) I would like to
> ask, how to handle this problem? And to which software needs to be
> requested for CVE? To MySQL itself (as described in option 1)? Or to
> every one software which uses MySQL (as described in option 2)?
> 
> I think you understand me, that MySQL DBD driver needs to be fixed,
> ideally ASAP. Bug report on github is from April 13 [4]. And as
> Oracle is not willing to do anything, I hope that people on public
> oss-security list give some advice how to handle this situation.
> 
> I'm CCing all relevant security teams, when replaying please do not
> forget to include them + me. Thanks!
> 
> --
> 
> [1] - https://dev.mysql.com/doc/refman/5.7/en/mysql-stmt-close.html
> [2] - https://dev.mysql.com/doc/refman/5.7/en/mysql-stmt-error.html
> [3] - https://dev.mysql.com/doc/refman/5.7/en/mysql-stmt-execute.html
> [4] - https://github.com/perl5-dbi/DBD-mysql/issues/120

Just to note that Oracle silently updated above documentation pages
after I sent this email. Original versions are available in web.archive:

[1] - http://web.archive.org/web/20161220021610/https://dev.mysql.com/doc/refman/5.7/en/mysql-stmt-close.html
[2] - http://web.archive.org/web/20161220021610/https://dev.mysql.com/doc/refman/5.7/en/mysql-stmt-error.html
[3] - http://web.archive.org/web/20161220021610/https://dev.mysql.com/doc/refman/5.7/en/mysql-stmt-execute.html

> (***) - This is not a first time! Previous two security issues
> reported by me were ignored too. Oracle is the worst company in
> handling security issues. It is useless to report them anything.
> They just start threaten if you make information about issue public.
> And they are not competent to start working on it or fix it in less
> then 6 months! Really I suggest to not report any security bug to
> Oracle, it is just wasting of time.

-- 
Pali Rohár
pali.rohar@...il.com

[ CONTENT OF TYPE application/pgp-signature SKIPPED ]

Powered by blists - more mailing lists

Your e-mail address:

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Powered by Openwall GNU/*/Linux - Powered by OpenVZ