Roundcube Webmail Virtualmin Privilege Escalation (CVE-2017-8114)

Roundcube Webmail is a browser-based multilingual IMAP client with an application-like user interface. Roundcube version 1.3-beta and probably previous versions do not properly sanitize client’s inputs. This can lead to an arbitrary password resets by authenticated users.

Roundcube uses multiple plugins that extend its functionalities. They are not part of the core application but can be installed individually. Roundcube comes with a number of plugins, and more third-party plugins are available for download.

Official password plugin in its virtualmin driver allows to an attacker, that has a valid username/password to login in his web panel, to execute malicious inputs. This could allow to an attacker to reset victim’s password and in some scenarios getting a system shell.

Technical Details

save() method in virtualmin.php uses an exec() function without properly filter user-supplied inputs:

class rcube_virtualmin_password {

   function save($currpass, $newpass) {

      ...

      $username = escapeshellcmd($username);
      $domain   = escapeshellcmd($domain);
      $newpass  = escapeshellcmd($newpass);
      $curdir   = RCUBE_PLUGINS_DIR . 'password/helpers';

      exec("$curdir/chgvirtualminpasswd modify-user --domain $domain --user $username --pass $newpass", $output, $returnvalue);

      ...

   }

}

escapeshellcmd() escapes any characters in a string that might be used to trick a shell command into executing arbitrary commands. This function should be used to make sure that any data coming from user input is escaped before this data is passed to the exec() or system() functions, or to the backtick operator.

escapeshellarg() adds single quotes around a string and quotes/escapes any existing single quotes allowing you to pass a string directly to a shell function and having it be treated as a single safe argument. This function should be used to escape individual arguments to shell functions coming from user input. The shell functions include exec(), system() and the backtick operator.

Thanks to escapeshellcmd() function an attacker can not execute arbitrary commands, but can use arbitrary modify-user parameters.

chgvirtualminpasswd is a simple wrapper to virtualmin that must run as root, which makes this injection more interesting. For the list of modify-user parameters see virtualmin-doc.

As example, a malicious user can inject a custom string as $newpass resetting the password of an arbitrary user. Attacker, authenticated as mark, can insert the following string as new password:

foo --user john --pass hacked 

The exec() function will execute following command:

chgvirtualminpasswd modify-user --domain localhost --user mark --pass foo --user john --pass hacked

In the above command the last --user and --pass parameters will be evaluated by chgvirtualminpasswd and the victim’s (john) password will be changed.

If ssh service is open and reachable the attacker can login using the victim’s credentials. Or, if ssh service is reachable but users can’t login via an interactive shell (e.g. has /bin/nologin or /dev/null shell), the attacker can change his shell (e.g to /bin/bash) injecting the following string as $newpass:

pass --shell /bin/bash

Vendor promptly fixes the issue and a similar bug in sasl driver. See Roundcube Project News.

Timeline

  • 2017-04-24: Vendor notification
  • 2017-04-25: Vendor fixes the bug on dev branch
  • 2017-04-27: Vendor releases a beta version
  • 2017-04-28: Vendor releases a stable version

The author is not responsible for the misuse of the information provided in this advisory.

Updated: