diff --git a/lhc_web/lib/core/lhcore/class.phpmailer.php b/lhc_web/lib/core/lhcore/class.phpmailer.php index 3edac2e07f..55e0a4f941 100644 --- a/lhc_web/lib/core/lhcore/class.phpmailer.php +++ b/lhc_web/lib/core/lhcore/class.phpmailer.php @@ -31,7 +31,7 @@ class PHPMailer * The PHPMailer Version number. * @var string */ - public $Version = '5.2.19'; + public $Version = '5.2.21'; /** * Email priority. @@ -1364,20 +1364,24 @@ public function postSend() */ protected function sendmailSend($header, $body) { - // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped by escapeshellcmd when popen is called due to safe mode. - if (!empty($this->Sender) || ini_get('safe_mode')) { + // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped. + if (!empty($this->Sender) and self::isShellSafe($this->Sender)) { if ($this->Mailer == 'qmail') { - $sendmail = sprintf('%s -f%s', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); + $sendmailFmt = '%s -f%s'; } else { - $sendmail = sprintf('%s -oi -f%s -t', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); + $sendmailFmt = '%s -oi -f%s -t'; } } else { if ($this->Mailer == 'qmail') { - $sendmail = sprintf('%s', escapeshellcmd($this->Sendmail)); + $sendmailFmt = '%s'; } else { - $sendmail = sprintf('%s -oi -t', escapeshellcmd($this->Sendmail)); + $sendmailFmt = '%s -oi -t'; } } + + // TODO: If possible, this should be changed to escapeshellarg. Needs thorough testing. + $sendmail = sprintf($sendmailFmt, escapeshellcmd($this->Sendmail), $this->Sender); + if ($this->SingleTo) { foreach ($this->SingleToArray as $toAddr) { if (!@$mail = popen($sendmail, 'w')) { @@ -1423,6 +1427,40 @@ protected function sendmailSend($header, $body) return true; } + /** + * Fix CVE-2016-10033 and CVE-2016-10045 by disallowing potentially unsafe shell characters. + * + * Note that escapeshellarg and escapeshellcmd are inadequate for our purposes, especially on Windows. + * @param string $string The string to be validated + * @see https://github.com/PHPMailer/PHPMailer/issues/924 CVE-2016-10045 bug report + * @access protected + * @return boolean + */ + protected static function isShellSafe($string) + { + // Future-proof + if (escapeshellcmd($string) !== $string + or !in_array(escapeshellarg($string), array("'$string'", "\"$string\"")) + ) { + return false; + } + + $length = strlen($string); + + for ($i = 0; $i < $length; $i++) { + $c = $string[$i]; + + // All other characters have a special meaning in at least one common shell, including = and +. + // Full stop (.) has a special meaning in cmd.exe, but its impact should be negligible here. + // Note that this does permit non-Latin alphanumeric characters based on the current locale. + if (!ctype_alnum($c) && strpos('@_-.', $c) === false) { + return false; + } + } + + return true; + } + /** * Send mail using the PHP mail() function. * @param string $header The message headers @@ -1444,8 +1482,8 @@ protected function mailSend($header, $body) //This sets the SMTP envelope sender which gets turned into a return-path header by the receiver if (!empty($this->Sender) and $this->validateAddress($this->Sender)) { // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped. - if (escapeshellcmd($this->Sender) === $this->Sender && in_array(escapeshellarg($this->Sender), array("'$this->Sender'", "\"$this->Sender\""))) { - $params = sprintf('-f%s', escapeshellarg($this->Sender)); + if (self::isShellSafe($this->Sender)) { + $params = sprintf('-f%s', $this->Sender); } } if (!empty($this->Sender) and !ini_get('safe_mode') and $this->validateAddress($this->Sender)) { diff --git a/lhc_web/lib/core/lhcore/class.smtp.php b/lhc_web/lib/core/lhcore/class.smtp.php index 6751879e73..4561389434 100644 --- a/lhc_web/lib/core/lhcore/class.smtp.php +++ b/lhc_web/lib/core/lhcore/class.smtp.php @@ -30,7 +30,7 @@ class SMTP * The PHPMailer SMTP version number. * @var string */ - const VERSION = '5.2.19'; + const VERSION = '5.2.21'; /** * SMTP line break constant. @@ -81,7 +81,7 @@ class SMTP * @deprecated Use the `VERSION` constant instead * @see SMTP::VERSION */ - public $Version = '5.2.19'; + public $Version = '5.2.21'; /** * SMTP server port number.