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
|
This patch is based on 2 commits containing fix for CVE-2016-10045 and CVE-2016-10033:
https://github.com/PHPMailer/PHPMailer/commit/9743ff5c7ee16e8d49187bd2e11149afb9485eae
https://github.com/PHPMailer/PHPMailer/commit/833c35fe39715c3d01934508987e97af1fbc1ba0
which were adjusted to PHPMailer_5.2.4 source code
diff -ru PHPMailer_5.2.4/class.phpmailer.php.orig PHPMailer_5.2.4/class.phpmailer.php
--- PHPMailer_5.2.4/class.phpmailer.php.orig
+++ PHPMailer_5.2.4/class.phpmailer.php
@@ -861,6 +861,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;
+ }
+
+ /**
* Sends mail using the $Sendmail program.
* @param string $header The message headers
* @param string $body The message body
@@ -869,8 +901,10 @@
* @return bool
*/
protected function SendmailSend($header, $body) {
- if ($this->Sender != '') {
- $sendmail = sprintf("%s -oi -f%s -t", escapeshellcmd($this->Sendmail), escapeshellarg($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)) {
+ // TODO: If possible, this should be changed to escapeshellarg. Needs thorough testing.
+ $sendmail = sprintf("%s -oi -f%s -t", escapeshellcmd($this->Sendmail), $this->Sender);
} else {
$sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail));
}
@@ -925,7 +959,9 @@
if (empty($this->Sender)) {
$params = "-oi ";
} else {
- $params = sprintf("-oi -f%s", $this->Sender);
+ if (self::isShellSafe($this->Sender)) {
+ $params = sprintf("-oi -f%s", $this->Sender);
+ }
}
if ($this->Sender != '' and !ini_get('safe_mode')) {
$old_from = ini_get('sendmail_from');
|