Vulnerabilities > CVE-2017-14474 - OS Command Injection vulnerability in Mysql-Mmm Mysql Multi-Master Replication Manager 2.2.1
Attack vector
NETWORK Attack complexity
LOW Privileges required
NONE Confidentiality impact
HIGH Integrity impact
HIGH Availability impact
HIGH Summary
In the MMM::Agent::Helpers::_execute function in MySQL Multi-Master Replication Manager (MMM) mmm_agentd 2.2.1, a specially crafted MMM protocol message can cause a shell command injection resulting in arbitrary command execution with the privileges of the mmm\_agentd process. An attacker that can initiate a TCP session with mmm\_agentd can trigger this vulnerability.
Vulnerable Configurations
Part | Description | Count |
---|---|---|
Application | 1 |
Common Weakness Enumeration (CWE)
Common Attack Pattern Enumeration and Classification (CAPEC)
- Command Line Execution through SQL Injection An attacker uses standard SQL injection methods to inject data into the command line for execution. This could be done directly through misuse of directives such as MSSQL_xp_cmdshell or indirectly through injection of data into the database that would be interpreted as shell commands. Sometime later, an unscrupulous backend application (or could be part of the functionality of the same application) fetches the injected data stored in the database and uses this data as command line arguments without performing proper validation. The malicious data escapes that data plane by spawning new commands to be executed on the host.
- Command Delimiters An attack of this type exploits a programs' vulnerabilities that allows an attacker's commands to be concatenated onto a legitimate command with the intent of targeting other resources such as the file system or database. The system that uses a filter or a blacklist input validation, as opposed to whitelist validation is vulnerable to an attacker who predicts delimiters (or combinations of delimiters) not present in the filter or blacklist. As with other injection attacks, the attacker uses the command delimiter payload as an entry point to tunnel through the application and activate additional attacks through SQL queries, shell commands, network scanning, and so on.
- Exploiting Multiple Input Interpretation Layers An attacker supplies the target software with input data that contains sequences of special characters designed to bypass input validation logic. This exploit relies on the target making multiples passes over the input data and processing a "layer" of special characters with each pass. In this manner, the attacker can disguise input that would otherwise be rejected as invalid by concealing it with layers of special/escape characters that are stripped off by subsequent processing steps. The goal is to first discover cases where the input validation layer executes before one or more parsing layers. That is, user input may go through the following logic in an application: In such cases, the attacker will need to provide input that will pass through the input validator, but after passing through parser2, will be converted into something that the input validator was supposed to stop.
- Argument Injection An attacker changes the behavior or state of a targeted application through injecting data or command syntax through the targets use of non-validated and non-filtered arguments of exposed services or methods.
- OS Command Injection In this type of an attack, an adversary injects operating system commands into existing application functions. An application that uses untrusted input to build command strings is vulnerable. An adversary can leverage OS command injection in an application to elevate privileges, execute arbitrary commands and compromise the underlying operating system.
Seebug
bulletinFamily | exploit |
description | ### Summary Multiple exploitable remote command injection vulnerabilities exist in the MySQL Master-Master Replication Manager (MMM) mmm_agentd daemon 2.2.1. mmm_agentd commonly runs with root privileges and does not require authentication by default. A specially crafted MMM protocol message can cause a shell command injection resulting in arbitrary command execution with the privileges of the mmm_agentd process. An attacker that can initiate a TCP session with mmm_agentd can trigger these vulnerabilities. ### Tested Versions MMM 2.2.1 ### Product URLs http://mysql-mmm.org/ ### CVSSv3 Score 9.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H ### CWE CWE-77: Improper Neutralization of Special Elements used in a Command ('Command Injection') ### Details MMM, the Multi-Master Replication Manager for MySQL, provides high availability to MySQL database clusters. Though superseded by more modern approaches, MMM was commonly used in high availability MySQL environments up through MySQL version 5.5. In an MMM environment, each MySQL server host runs the mmm_agentd agent. In its default configuration, mmm_agentd does not require authentication and typically runs as root because it requires sufficient privileges to reconfigure network interfaces. mmm_agentd contains multiple remotely exploitable command injection vulnerabilities. Therefore, in many MMM environments, if an unauthenticated network attacker can make a TCP connection to the mmm_agentd process, they can run arbitrary commands as root. This vulnerability occurs because mmm_agentd includes attacker-supplied input in shell commands in multiple locations without appropriate sanitization. For example, the MMM SET_STATUS protocol message can be used to assign a number of roles to an mmm_agentd host. Roles are specified as a comma-separated list of role_name(ip_addr) pairs (e.g. role_a(10.10.10.10),role_b(10.10.10.11)). MMM::Common::Role::from_string() in lib/Common/Role.pm uses the following regular expression to parse the role name and IP address: /(.*)\((.*)\)/. Thus, everything before the last opening parenthesis will interpreted as the role name and all remaining characters up to the last closing parenthesis will be interpreted as the role IP address. An attacker can construct malicious IP address values that will cause subsequent role handling code to invoke arbitrary commands. For example: ``` role_a(10.10.10.10`malicious_command`) ``` Malicious IP address values are subject to interpretation by the shell both in mmm_agentd and in helper applications called by mmm_agentd. Role IP address values should be validated to ensure that only expected values are specified. However, because other data flows may allow malicious input to reach vulnerable functions, all dynamic values incorporated into shell commands should be sanitized to ensure that shell metacharacters do not introduce additional arguments or execute unintended commands. Limitations: Due to the mmm_agentd protocol format, injected commands cannot contain the following characters: ',', '|', '(', and '\n' #### CVE-2017-14474 - MMM::Agent::Helpers::_execute() The MMM::Agent::Helpers::_execute() function accepts a command and an string containing arguments for the command. It constructs a Bourne shell command line by concatenating the path to the requested command, the mmm_agentd config file, and the specified arguments. _execute() runs the resulting command using the the Perl backtick operator as follows. ``` # lib/Agent/Helpers.pm 162 sub _execute($$$) { 163 my $command = shift; 164 my $params = shift; 165 my $return_all = shift; 166 167 my $path = $main::agent->bin_path . "/agent/$command"; 168 my $config_file = $main::agent->config_file; 169 $params = '' unless defined($params); 170 171 DEBUG "Executing $path $params"; 172 my $res = `$path $config_file $params`; ``` Because _execute() does not sanitize $params, any shell metacharacters present in $params will be interpreted by the shell. There are several code paths that can cause _execute() to be called with untrusted input in the $params variable. To handle roles that have been added and removed, mmm_agentd will invoke MMM::Agent::Helpers::configure_ip($if, $ip) for each added role and MMM::Agent::Helpers::clear_ip($if, $ip) for each deleted role with $ip set to the IP address value specified for the role. Both, functions pass $ip to _execute() without sanitization. ``` # lib/Agent/Helpers.pm 45 sub configure_ip($$) { 46 my $if = shift; 47 my $ip = shift; 48 return _execute('configure_ip', "$if $ip"); 49 } ... 60 sub clear_ip($$) { 61 my $if = shift; 62 my $ip = shift; 63 return _execute('clear_ip', "$if $ip"); 64 } 65 ``` As noted above role IP addresses can contain arbitrary content, modulo a few character restrictions, allowing an attacker to execute arbitrary shell commands. Additionally, the GET_SYSTEM_STATUS and CLEAR_BAD_ROLES MMM protocol messages can be used to invoke MMM::Agent::Helpers::check_ip($if, $ip) on the IP address value of each role. check_ip() also passes the untrusted $ip value to _execute() without further sanitization. ``` # lib/Agent/Helpers.pm 29 sub check_ip($$) { 30 my $if = shift; 31 my $ip = shift; 32 return _execute('check_ip', "$if $ip"); 33 } ``` Because input may be derived from a variety of (potentially untrusted) sources, _execute() should be modified to take an array of discrete command arguments and to either avoid shell interpretation by using execv-like functionality or quote command arguments to prevent shell interpretation. #### CVE-2017-14475 - MMM::Agent::Helpers::Network::add_ip() (Linux) As seen above, in order to configure a new IP address mmm_agentd invokes: ``` /path/to/agent/configure_ip /path/to/mmm_agent.conf $if $ip ``` To add the IP address to the specified interface, the configure_ip helper command invokes MMM::Agent::Helpers::Network::add_ip(). Which runs the following command on Linux hosts: ``` # lib/Agent/Helpers/Network.pm 70 $output = `/sbin/ip addr add $ip/32 dev $if`; ``` As a result, a malicious role IP address value that has been quoted to prevent interpretation in MMM::Agent::Helpers::_execute() will arrive to add_ip() in unquoted form allowing the execution of arbitrary commands. #### CVE-2017-14476 - MMM::Agent::Helpers::Network::add_ip() (Solaris) As seen above, in order to configure a new IP address mmm_agentd invokes: ``` /path/to/agent/configure_ip /path/to/mmm_agent.conf $if $ip ``` To add the IP address to the specified interface, the configure_ip helper command invokes MMM::Agent::Helpers::Network::add_ip(). Which runs the following command on Solaris hosts: ``` # lib/Agent/Helpers/Network.pm 74 $output = `/usr/sbin/ifconfig $if addif $ip`; ``` As a result, a malicious role IP address value that has been quoted to prevent interpretation in MMM::Agent::Helpers::_execute() will arrive to add_ip() in unquoted form allowing the execution of arbitrary commands. #### CVE-2017-14477 - MMM::Agent::Helpers::Network::add_ip() (FreeBSD) As seen above, in order to configure a new IP address mmm_agentd invokes: ``` /path/to/agent/configure_ip /path/to/mmm_agent.conf $if $ip ``` To add the IP address to the specified interface, the configure_ip helper command invokes MMM::Agent::Helpers::Network::add_ip(). Which runs the following command on FreeBSD hosts: ``` # lib/Agent/Helpers/Network.pm 84 $output = `/sbin/ifconfig $if inet $ip netmask 255.255.255.255 alias`; ``` As a result, a malicious role IP address value that has been quoted to prevent interpretation in MMM::Agent::Helpers::_execute() will arrive to add_ip() in unquoted form allowing the execution of arbitrary commands. #### CVE-2017-14478 - MMM::Agent::Helpers::Network::clear_ip() (Linux) As seen above, to remove a deleted role's IP address, mmm_agentd invokes: ``` /path/to/agent/clear_ip /path/to/mmm_agent.conf $if $ip ``` To remove the IP address from the specified interface, the clear_ip helper command invokes MMM::Agent::Helpers::Network::clear_ip(). Which runs the following command on Linux hosts: ``` # lib/Agent/Helpers/Network.pm 106 $output = `/sbin/ip addr del $ip/32 dev $if`; ``` As a result, a malicious role IP address value that has been quoted to prevent interpretation in MMM::Agent::Helpers::_execute() will arrive to clear_ip() in unquoted form allowing the execution of arbitrary commands. #### CVE-2017-14479 - MMM::Agent::Helpers::Network::clear_ip() (Solaris) As seen above, to remove a deleted role's IP address, mmm_agentd invokes: ``` /path/to/agent/clear_ip /path/to/mmm_agent.conf $if $ip ``` To remove the IP address from the specified interface, the clear_ip helper command invokes MMM::Agent::Helpers::Network::clear_ip(). Which runs the following command on Solaris hosts: ``` # lib/Agent/Helpers/Network.pm 110 $output = `/usr/sbin/ifconfig $if removeif $ip`; ``` As a result, a malicious role IP address value that has been quoted to prevent interpretation in MMM::Agent::Helpers::_execute() will arrive to clear_ip() in unquoted form allowing the execution of arbitrary commands. #### CVE-2017-14480 - MMM::Agent::Helpers::Network::clear_ip() (FreeBSD) As seen above, to remove a deleted role's IP address, mmm_agentd invokes: ``` /path/to/agent/clear_ip /path/to/mmm_agent.conf $if $ip ``` To remove the IP address from the specified interface, the clear_ip helper command invokes MMM::Agent::Helpers::Network::clear_ip(). Which runs the following command on FreeBSD hosts: ``` # lib/Agent/Helpers/Network.pm 114 $output = `/sbin/ifconfig $if inet $ip -alias`; ``` As a result, a malicious role IP address value that has been quoted to prevent interpretation in MMM::Agent::Helpers::_execute() will arrive to clear_ip() in unquoted form allowing the execution of arbitrary commands. #### CVE-2017-14481 - MMM::Agent::Helpers::Network::send_arp() (Solaris) After a new IP address has been configured successfully, the implementation of the configure_ip helper command will send gratuitous ARPs: ``` # lib/Agent/Helpers/Actions.pm 47 sub configure_ip($$) { 48 my $if = shift; 49 my $ip = shift; 50 51 if (MMM::Agent::Helpers::Network::check_ip($if, $ip)) { 52 _exit_ok('IP address is configured'); 53 } 54 55 if (!MMM::Agent::Helpers::Network::add_ip($if, $ip)) { 56 _exit_error("Could not configure ip adress $ip on interface $if!"); 57 } 58 MMM::Agent::Helpers::Network::send_arp($if, $ip); 59 _exit_ok(); 60 } # lib/Agent/Helpers/Network.pm 129 sub send_arp($$) { 130 my $if = shift; 131 my $ip = shift; ... 151 elsif ($OSNAME eq 'solaris') { 152 # Get params for send_arp 153 my $ipaddr = `/usr/sbin/ifconfig $if`; 154 155 # Get broadcast address and netmask 156 $ipaddr =~ /netmask\s*([0-9a-f]+)\s*broadcast\s*([\d\.]+)/i; 157 my $if_bcast = $1; 158 my $if_mask = $2; 159 `/bin/send_arp -i 100 -r 5 -p /tmp/send_arp $if $ip auto $if_bcast $if_mask`; 160 } ``` send_arp() does not sanitize the value of $ip before interpolating it into shell commands on Solaris systems. While dangerous, this particular instance may not be currently exploitable because send_arp() is only called if add_ip() succeeds and add_ip() will return with failure if MMM::Agent::Helpers::Network::check_ip() cannot verify that the IP address configuration attempt succeeded. check_ip() currently attempts to match the the full text of the role IP address against the value obtained from the operating system. Thus, additional non-IP address characters in $ip will cause check_ip() to return false: ``` # lib/Agent/Helpers/Network.pm 32 sub check_ip($$) { 33 my $if = shift; 34 my $ip = shift; 35 36 my $output; 37 if ($OSNAME eq 'linux') { 38 $output = `/sbin/ip addr show dev $if`; 39 _exit_error("Could not check if ip $ip is configured on $if: $output") if ($? >> 8 == 255); 40 } 41 elsif ($OSNAME eq 'solaris') { 42 # FIXME $if is not used here 43 $output = `/usr/sbin/ifconfig -a | grep inet`; 44 _exit_error("Could not check if ip $ip is configured on $if: $output") if ($? >> 8 == 255); 45 } 46 elsif ($OSNAME eq 'freebsd') { 47 $output = `/sbin/ifconfig $if | grep inet`; 48 _exit_error("Could not check if ip $ip is configured on $if: $output") if ($? >> 8 == 255); 49 } 50 else { 51 _exit_error("ERROR: Unsupported platform!"); 52 } 53 54 return ($output =~ /\D+$ip\D+/) ? 1 : 0; 55 } ``` Nevertheless, send_arp() should be fixed to sanitize its shell command arguments as well, because this behavior may change in subsequent releases. ### Mitigation The impact of these vulnerabilities can be lessened by configuring mmm_agentd to require TLS mutual authentication and by using network ACLs to prevent hosts other than legitimate mmm_mond hosts from accessing mmm_agentd. To enable TLS mutual authentication follow the steps below (examples provided using gnutls certtool): * Generate unique mmm_agentd and mmm_mond CAs for MMM. mmm_agentd and mmm_mond will accept any certificate signed by the CA that they have been configured to trust. Therefore, to prevent non-MMM nodes from connecting to mmm_agentd and to prevent malicious mmm_agentd hosts from impersonating mmm_mond, fresh separate CAs should be created to endorse mmm_agentd and mmm_mond certificates. ``` # Generate mmm_agentd CA certificate certtool --generate-privkey --outfile agentd-ca.key certtool --generate-self-signed --load-privkey agentd-ca.key \ --outfile agentd-ca.pem --template /dev/stdin <<EOT cn = "mmm_agentd CA" expiration_days = 3650 ca path_len = -1 signing_key encryption_key cert_signing_key organization = unit = locality = state = country = uid = EOT # Generate mmm\_mond CA certificate certtool --generate-privkey --outfile mond-ca.key certtool --generate-self-signed --load-privkey mond-ca.key \ --outfile mond-ca.pem --template /dev/stdin <<EOT cn = "mmm_mond CA" expiration_days = 3650 ca path_len = -1 signing_key encryption_key cert_signing_key organization = unit = locality = state = country = uid = EOT ``` * Generate a private key and certificate for each mmm_agentd host (e.g. db1): ``` # Generate mmm_agentd cert certtool --generate-privkey --outfile db1.key certtool --generate-certificate --load-privkey db1.key \ --outfile db1.pem \ --load-ca-certificate agentd-ca.pem \ --load-ca-privkey agentd-ca.key \ --template /dev/stdin <<EOT cn = "db1 mmm_agentd" expiration_days = 365 signing_key encryption_key tls_www_client tls_www_server organization = unit = locality = state = country = uid = EOT ``` * Generate a private key and certificate for each mmm_mond host (e.g. mmm_mond1): ``` # Generate mmm_mond cert certtool --generate-privkey --outfile mmm_mond1.key certtool --generate-certificate --load-privkey mmm_mond1.key \ --outfile mmm_mond1.pem \ --load-ca-certificate mond-ca.pem \ --load-ca-privkey mond-ca.key \ --template /dev/stdin <<EOT cn = "mmm_mond1" expiration_days = 365 signing_key encryption_key tls_www_client tls_www_server organization = unit = locality = state = country = uid = EOT ``` * Configure mmm_agentd hosts to require mmm_mond clients to identify with mmm_mond CA certificates. Add a section such as the following to /etc/.../mmm_agent.conf: ``` <socket> type ssl cert_file /path/to/db1.pem key_file /path/to/db1.key ca_file /path/to/mond-ca.pem </socket> ``` * Configure mmm_mond hosts to require mmm_agentd daemons to identify with mmm_agentd CA certificates. Add a section such as the following to /etc/.../mmm_mon.conf: ``` <socket> type ssl cert_file /path/to/mmm_mond1.pem key_file /path/to/mmm_mond1.key ca_file /path/to/agentd-ca.pem </socket> ``` * Restart mmm_agentd and mmm_mond processes ### Timeline * 2017-12-07 - Initial vendor contact * 2018-01-11 - 2nd vendor contact * 2018-03-06 - 3rd vendor contact (90 day notice) * 2018-04-17 - Vendor acknowledged * 2018-05-04 - Vendor confirmed patch * 2018-05-07 - Public Release |
id | SSV:97295 |
last seen | 2018-06-08 |
modified | 2018-05-17 |
published | 2018-05-17 |
reporter | Knownsec |
title | Multi-Master Replication Manager for MySQL mmm_agentd Remote Command Injection Vulnerabilities |
Talos
id | TALOS-2017-0501 |
last seen | 2019-05-29 |
published | 2018-05-07 |
reporter | Talos Intelligence |
source | http://www.talosintelligence.com/vulnerability_reports/TALOS-2017-0501 |
title | Multi-Master Replication Manager for MySQL mmm_agentd Remote Command Injection Vulnerabilities |