Bug #1802 MySql service will not start if configured to run as a normal user (with patch)
Submitted: 11 Nov 2003 1:14 Modified: 13 Dec 2003 12:30
Reporter: Richard Hansen Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server Severity:S2 (Serious)
Version:4.0.x, 3.23.54-3.23.58 OS:Microsoft Windows (Windows NT/2K/XP)
Assigned to: Miguel Solorzano

[11 Nov 2003 1:14] Richard Hansen
Description:
If MySQL is being started as a service, and that service is configured to run as a non-Administrator account, the service will fail to start.

The cause of this problem is in line 501 of sql/nt_servc.cc.  The function NTService::IsService checks to see whether the specified service exists on the machine by checking if it has full access to the service (SERVICE_ALL_ACCESS).  By default, only Administrators have this right.  When run as a non-Administrator, the OpenService call will fail with ERROR_ACCESS_DENIED.  Because of the structure of the code, this error has the same effect as the expected ERROR_SERVICE_DOES_NOT_EXIST (IsService returns false, leading mysqld to think it's being run as a console app, not a service).

Workaround:  Change the DACL for the service to grant the non-Administrator account SERVICE_ALL_ACCESS.  For example, get scacl.exe from LS-Tools (http://www.losoft.de/lstools.html) and run the following command:
    scacl.exe MySql /E /G mysqluser:F

Security consequences of this bug:  Because the mysqld service cannot run as a non-Admininstrator without doing the workaround, an attacker might be able to gain complete control over the Windows system if he manages to compromise the mysqld server.

How to repeat:
In Windows XP:
  * Open the Services management console (Start..Run, services.msc).
  * Double click the MySql service (or any other MySQL service set up using "mysqld --install [optional-service-name]")
  * Click on the "Log On" tab
  * Under "Log on as" choose "This account"
  * Choose a non-Administrator account with sufficient file system rights and the "log on as a service" right
  * Enter the password for that account
  * Hit OK, start the service, and watch it fail
  * While waiting for the service to fail, you can verify that mysqld is actually running.  Connect to it from a client before the service times out.

Suggested fix:
The following patch should fix the bug.  It changes the desired access from SERVICE_ALL_ACCESS (which only Administrators have) to SERVICE_QUERY_STATUS (which is a read-only access that just about everyone has).  Because mysqld doesn't actually do anything with the service (the status isn't queried, no changes are made, etc.) it doesn't matter which access right is requested in OpenService() -- the only thing that matters is whether OpenService() returns ERROR_SERVICE_DOES_NOT_EXIST or not.

===== sql/nt_servc.cc 1.13 vs edited =====
--- 1.13/sql/nt_servc.cc        Tue Jul 01 07:40:13 2003
+++ edited/sql/nt_servc.cc      Thu Oct 30 18:02:05 2003
@@ -498,7 +498,7 @@

   if (scm = OpenSCManager(0, 0,SC_MANAGER_ENUMERATE_SERVICE))
   {
-    if ((service = OpenService(scm,ServiceName, SERVICE_ALL_ACCESS )))
+    if ((service = OpenService(scm,ServiceName, SERVICE_QUERY_STATUS )))
     {
       ret_value=TRUE;
       CloseServiceHandle(service);
[11 Nov 2003 1:32] Richard Hansen
Other people have noticed the problem.  Look at the user comments on this MySQL manual page:

http://www.mysql.com/doc/en/Changing_MySQL_user.html
[16 Nov 2003 18:01] Miguel Solorzano
Thank you for the bug report, it makes sense to me.
[13 Dec 2003 12:30] Michael Widenius
Thank you for your bug report. This issue has been committed to our
source repository of that product and will be incorporated into the
next release.

If necessary, you can access the source repository and build the latest
available version, including the bugfix, yourself. More information 
about accessing the source trees is available at
    http://www.mysql.com/doc/en/Installing_source_tree.html

Additional info:

Thanks a lot for helping us fix this!

The fix will be in MySQL 4.0.17!