From de3affdd0d7ebd5560d39c47838f8dcc0835fc01 Mon Sep 17 00:00:00 2001
From: Simey Lameze <simey@moodle.com>
Date: Thu, 1 Aug 2019 20:46:22 +0800
Subject: [PATCH] MDL-65749 lib: fix phpmailer file handling

---
 lib/phpmailer/README_MOODLE.txt |  3 +++
 lib/phpmailer/src/PHPMailer.php | 29 ++++++++++++++++++++++++-----
 2 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/lib/phpmailer/README_MOODLE.txt b/lib/phpmailer/README_MOODLE.txt
index 6b176304c4b..a64500af162 100644
--- a/lib/phpmailer/README_MOODLE.txt
+++ b/lib/phpmailer/README_MOODLE.txt
@@ -29,3 +29,6 @@ Local changes (to verify/apply with new imports):
     lib/phpmailer/src/PHPMailer.php: FILTER_FLAG_HOST_REQUIRED is deprecated and
     implied with FILTER_VALIDATE_URL. This was fixed upstream by
     https://github.com/PHPMailer/PHPMailer/pull/1551
+
+- MDL-65749: Applied security patch for mitigating CVE-2018-19296
+    https://github.com/PHPMailer/PHPMailer/commit/8e653bb79643abad30ae60b1aad6966c0810b896
\ No newline at end of file
diff --git a/lib/phpmailer/src/PHPMailer.php b/lib/phpmailer/src/PHPMailer.php
index b5b98652054..d006dc5df61 100644
--- a/lib/phpmailer/src/PHPMailer.php
+++ b/lib/phpmailer/src/PHPMailer.php
@@ -1423,7 +1423,10 @@ class PHPMailer
             if (!empty($this->DKIM_domain)
                 and !empty($this->DKIM_selector)
                 and (!empty($this->DKIM_private_string)
-                    or (!empty($this->DKIM_private) and file_exists($this->DKIM_private))
+                    or (!empty($this->DKIM_private)
+                        and static::isPermittedPath($this->DKIM_private)
+                        and file_exists($this->DKIM_private)
+                    )
                 )
             ) {
                 $header_dkim = $this->DKIM_Add(
@@ -1600,6 +1603,20 @@ class PHPMailer
         return true;
     }
 
+    /**
+     * Check whether a file path is of a permitted type.
+     * Used to reject URLs and phar files from functions that access local file paths,
+     * such as addAttachment.
+     *
+     * @param string $path A relative or absolute path to a file.
+     *
+     * @return bool
+     */
+    protected static function isPermittedPath($path)
+    {
+        return !preg_match('#^[a-z]+://#i', $path);
+    }
+
     /**
      * Send mail using the PHP mail() function.
      *
@@ -1989,7 +2006,7 @@ class PHPMailer
         // There is no English translation file
         if ('en' != $langcode) {
             // Make sure language file path is readable
-            if (!file_exists($lang_file)) {
+            if (!static::isPermittedPath($lang_file) || !file_exists($lang_file)) {
                 $foundlang = false;
             } else {
                 // Overwrite language-specific strings.
@@ -2727,6 +2744,8 @@ class PHPMailer
      * Add an attachment from a path on the filesystem.
      * Never use a user-supplied path to a file!
      * Returns false if the file could not be found or read.
+     * Explicitly *does not* support passing URLs; PHPMailer is not an HTTP client.
+     * If you need to do that, fetch the resource yourself and pass it in via a local file or string.
      *
      * @param string $path        Path to the attachment
      * @param string $name        Overrides the attachment name
@@ -2741,7 +2760,7 @@ class PHPMailer
     public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment')
     {
         try {
-            if (!@is_file($path)) {
+            if (!static::isPermittedPath($path) || !@is_file($path)) {
                 throw new Exception($this->lang('file_access') . $path, self::STOP_CONTINUE);
             }
 
@@ -2923,7 +2942,7 @@ class PHPMailer
     protected function encodeFile($path, $encoding = 'base64')
     {
         try {
-            if (!file_exists($path)) {
+            if (!static::isPermittedPath($path) || !file_exists($path)) {
                 throw new Exception($this->lang('file_open') . $path, self::STOP_CONTINUE);
             }
             $file_buffer = file_get_contents($path);
@@ -3263,7 +3282,7 @@ class PHPMailer
      */
     public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline')
     {
-        if (!@is_file($path)) {
+        if (!static::isPermittedPath($path) || !@is_file($path)) {
             $this->setError($this->lang('file_access') . $path);
 
             return false;
-- 
2.20.1

