@@ -31,7 +31,7 @@ class PHPMailer
31
31
* The PHPMailer Version number.
32
32
* @var string
33
33
*/
34
- public $ Version = '5.2.19 ' ;
34
+ public $ Version = '5.2.21 ' ;
35
35
36
36
/**
37
37
* Email priority.
@@ -1364,19 +1364,24 @@ public function postSend()
1364
1364
*/
1365
1365
protected function sendmailSend ($ header , $ body )
1366
1366
{
1367
- if (!empty ($ this ->Sender )) {
1367
+ // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
1368
+ if (!empty ($ this ->Sender ) and self ::isShellSafe ($ this ->Sender )) {
1368
1369
if ($ this ->Mailer == 'qmail ' ) {
1369
- $ sendmail = sprintf ( '%s -f%s ' , escapeshellcmd ( $ this -> Sendmail ), escapeshellarg ( $ this -> Sender )) ;
1370
+ $ sendmailFmt = '%s -f%s ' ;
1370
1371
} else {
1371
- $ sendmail = sprintf ( '%s -oi -f%s -t ' , escapeshellcmd ( $ this -> Sendmail ), escapeshellarg ( $ this -> Sender )) ;
1372
+ $ sendmailFmt = '%s -oi -f%s -t ' ;
1372
1373
}
1373
1374
} else {
1374
1375
if ($ this ->Mailer == 'qmail ' ) {
1375
- $ sendmail = sprintf ( '%s ' , escapeshellcmd ( $ this -> Sendmail )) ;
1376
+ $ sendmailFmt = '%s ' ;
1376
1377
} else {
1377
- $ sendmail = sprintf ( '%s -oi -t ' , escapeshellcmd ( $ this -> Sendmail )) ;
1378
+ $ sendmailFmt = '%s -oi -t ' ;
1378
1379
}
1379
1380
}
1381
+
1382
+ // TODO: If possible, this should be changed to escapeshellarg. Needs thorough testing.
1383
+ $ sendmail = sprintf ($ sendmailFmt , escapeshellcmd ($ this ->Sendmail ), $ this ->Sender );
1384
+
1380
1385
if ($ this ->SingleTo ) {
1381
1386
foreach ($ this ->SingleToArray as $ toAddr ) {
1382
1387
if (!@$ mail = popen ($ sendmail , 'w ' )) {
@@ -1422,6 +1427,40 @@ protected function sendmailSend($header, $body)
1422
1427
return true ;
1423
1428
}
1424
1429
1430
+ /**
1431
+ * Fix CVE-2016-10033 and CVE-2016-10045 by disallowing potentially unsafe shell characters.
1432
+ *
1433
+ * Note that escapeshellarg and escapeshellcmd are inadequate for our purposes, especially on Windows.
1434
+ * @param string $string The string to be validated
1435
+ * @see https://github.com/PHPMailer/PHPMailer/issues/924 CVE-2016-10045 bug report
1436
+ * @access protected
1437
+ * @return boolean
1438
+ */
1439
+ protected static function isShellSafe ($ string )
1440
+ {
1441
+ // Future-proof
1442
+ if (escapeshellcmd ($ string ) !== $ string
1443
+ or !in_array (escapeshellarg ($ string ), array ("' $ string' " , "\"$ string \"" ))
1444
+ ) {
1445
+ return false ;
1446
+ }
1447
+
1448
+ $ length = strlen ($ string );
1449
+
1450
+ for ($ i = 0 ; $ i < $ length ; $ i ++) {
1451
+ $ c = $ string [$ i ];
1452
+
1453
+ // All other characters have a special meaning in at least one common shell, including = and +.
1454
+ // Full stop (.) has a special meaning in cmd.exe, but its impact should be negligible here.
1455
+ // Note that this does permit non-Latin alphanumeric characters based on the current locale.
1456
+ if (!ctype_alnum ($ c ) && strpos ('@_-. ' , $ c ) === false ) {
1457
+ return false ;
1458
+ }
1459
+ }
1460
+
1461
+ return true ;
1462
+ }
1463
+
1425
1464
/**
1426
1465
* Send mail using the PHP mail() function.
1427
1466
* @param string $header The message headers
@@ -1442,7 +1481,10 @@ protected function mailSend($header, $body)
1442
1481
$ params = null ;
1443
1482
//This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
1444
1483
if (!empty ($ this ->Sender ) and $ this ->validateAddress ($ this ->Sender )) {
1445
- $ params = sprintf ('-f%s ' , escapeshellarg ($ this ->Sender ));
1484
+ // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
1485
+ if (self ::isShellSafe ($ this ->Sender )) {
1486
+ $ params = sprintf ('-f%s ' , $ this ->Sender );
1487
+ }
1446
1488
}
1447
1489
if (!empty ($ this ->Sender ) and !ini_get ('safe_mode ' ) and $ this ->validateAddress ($ this ->Sender )) {
1448
1490
$ old_from = ini_get ('sendmail_from ' );
0 commit comments