1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
|
diff -Nur libphp-phpmailer-5.2.14+dfsg.orig/class.phpmailer.php libphp-phpmailer-5.2.14+dfsg.new/class.phpmailer.php
--- libphp-phpmailer-5.2.14+dfsg.orig/class.phpmailer.php 2015-11-01 10:15:28.000000000 +0000
+++ libphp-phpmailer-5.2.14+dfsg.new/class.phpmailer.php 2017-01-02 14:20:47.484824213 +0000
@@ -1329,19 +1329,24 @@
*/
protected function sendmailSend($header, $body)
{
- if ($this->Sender != '') {
+ // 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')) {
@@ -1388,6 +1393,38 @@
}
/**
+ * 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
* @param string $body The message body
@@ -1404,12 +1441,14 @@
}
$to = implode(', ', $toArr);
- if (empty($this->Sender)) {
- $params = ' ';
- } else {
- $params = sprintf('-f%s', $this->Sender);
+ $params = null;
+ 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 (self::isShellSafe($this->Sender)) {
+ $params = sprintf('-f%s', $this->Sender);
+ }
}
- if ($this->Sender != '' and !ini_get('safe_mode')) {
+ if (!empty($this->Sender) and !ini_get('safe_mode') and $this->validateAddress($this->Sender)) {
$old_from = ini_get('sendmail_from');
ini_set('sendmail_from', $this->Sender);
}
@@ -1463,10 +1502,10 @@
if (!$this->smtpConnect($this->SMTPOptions)) {
throw new phpmailerException($this->lang('smtp_connect_failed'), self::STOP_CRITICAL);
}
- if ('' == $this->Sender) {
- $smtp_from = $this->From;
- } else {
+ if (!empty($this->Sender) and $this->validateAddress($this->Sender)) {
$smtp_from = $this->Sender;
+ } else {
+ $smtp_from = $this->From;
}
if (!$this->smtp->mail($smtp_from)) {
$this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError()));
|