Skip to content

Commit 88c65aa

Browse files
committed
External libraries: Improve attachment handling in PHPMailer
Props: audrasjb, ayeshrajans, desrosj, peterwilsoncc, xknown. Partially merges [50799] to the 5.0 branch. git-svn-id: https://develop.svn.wordpress.org/branches/5.0@50854 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 63c477d commit 88c65aa

File tree

1 file changed

+45
-7
lines changed

1 file changed

+45
-7
lines changed

src/wp-includes/class-phpmailer.php

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,9 +1294,12 @@ public function preSend()
12941294

12951295
// Sign with DKIM if enabled
12961296
if (!empty($this->DKIM_domain)
1297-
&& !empty($this->DKIM_selector)
1298-
&& (!empty($this->DKIM_private_string)
1299-
|| (!empty($this->DKIM_private) && file_exists($this->DKIM_private))
1297+
and !empty($this->DKIM_selector)
1298+
and (!empty($this->DKIM_private_string)
1299+
or (!empty($this->DKIM_private)
1300+
and self::isPermittedPath($this->DKIM_private)
1301+
and file_exists($this->DKIM_private)
1302+
)
13001303
)
13011304
) {
13021305
$header_dkim = $this->DKIM_Add(
@@ -1461,6 +1464,39 @@ protected static function isShellSafe($string)
14611464
return true;
14621465
}
14631466

1467+
/**
1468+
* Check whether a file path is of a permitted type.
1469+
* Used to reject URLs and phar files from functions that access local file paths,
1470+
* such as addAttachment.
1471+
* @param string $path A relative or absolute path to a file.
1472+
* @return bool
1473+
*/
1474+
protected static function isPermittedPath($path)
1475+
{
1476+
//Matches scheme definition from https://tools.ietf.org/html/rfc3986#section-3.1
1477+
return !preg_match('#^[a-z][a-z\d+.-]*://#i', $path);
1478+
}
1479+
1480+
/**
1481+
* Check whether a file path is safe, accessible, and readable.
1482+
*
1483+
* @param string $path A relative or absolute path to a file
1484+
*
1485+
* @return bool
1486+
*/
1487+
protected static function fileIsAccessible($path)
1488+
{
1489+
if (!self::isPermittedPath($path)) {
1490+
return false;
1491+
}
1492+
$readable = file_exists($path);
1493+
//If not a UNC path (expected to start with \\), check read permission, see #2069
1494+
if (strpos($path, '\\\\') !== 0) {
1495+
$readable = $readable && is_readable($path);
1496+
}
1497+
return $readable;
1498+
}
1499+
14641500
/**
14651501
* Send mail using the PHP mail() function.
14661502
* @param string $header The message headers
@@ -1784,7 +1820,7 @@ public function setLanguage($langcode = 'en', $lang_path = '')
17841820
// There is no English translation file
17851821
if ($langcode != 'en') {
17861822
// Make sure language file path is readable
1787-
if (!is_readable($lang_file)) {
1823+
if (!self::fileIsAccessible($lang_file)) {
17881824
$foundlang = false;
17891825
} else {
17901826
// Overwrite language-specific strings.
@@ -2495,6 +2531,8 @@ public function textLine($value)
24952531
* Add an attachment from a path on the filesystem.
24962532
* Never use a user-supplied path to a file!
24972533
* Returns false if the file could not be found or read.
2534+
* Explicitly *does not* support passing URLs; PHPMailer is not an HTTP client.
2535+
* If you need to do that, fetch the resource yourself and pass it in via a local file or string.
24982536
* @param string $path Path to the attachment.
24992537
* @param string $name Overrides the attachment name.
25002538
* @param string $encoding File encoding (see $Encoding).
@@ -2506,7 +2544,7 @@ public function textLine($value)
25062544
public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment')
25072545
{
25082546
try {
2509-
if (!@is_file($path)) {
2547+
if (!self::fileIsAccessible($path)) {
25102548
throw new phpmailerException($this->lang('file_access') . $path, self::STOP_CONTINUE);
25112549
}
25122550

@@ -2687,7 +2725,7 @@ protected function attachAll($disposition_type, $boundary)
26872725
protected function encodeFile($path, $encoding = 'base64')
26882726
{
26892727
try {
2690-
if (!is_readable($path)) {
2728+
if (!self::fileIsAccessible($path)) {
26912729
throw new phpmailerException($this->lang('file_open') . $path, self::STOP_CONTINUE);
26922730
}
26932731
$magic_quotes = get_magic_quotes_runtime();
@@ -3031,7 +3069,7 @@ public function addStringAttachment(
30313069
*/
30323070
public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline')
30333071
{
3034-
if (!@is_file($path)) {
3072+
if (!self::fileIsAccessible($path)) {
30353073
$this->setError($this->lang('file_access') . $path);
30363074
return false;
30373075
}

0 commit comments

Comments
 (0)