Sanitize user-supplied attachment filename [CVE-2018-8741]
authorpdontthink <pdontthink@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Wed, 4 Apr 2018 03:19:39 +0000 (03:19 +0000)
committerpdontthink <pdontthink@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Wed, 4 Apr 2018 03:19:39 +0000 (03:19 +0000)
git-svn-id: https://svn.code.sf.net/p/squirrelmail/code/trunk/squirrelmail@14753 7612ce4b-ef26-0410-bec9-ea0150e637f0

doc/ChangeLog
src/compose.php

index 446b7eb..e87ff63 100644 (file)
@@ -417,6 +417,7 @@ Version 1.5.2 - SVN
     as replied or forwarded when the draft is finally sent
   - Added option to allow returning to the message one had been
     replying to after sending 
+  - Sanitize user-supplied attachment filenames [CVE-2017-7692]
 
 Version 1.5.1 (branched on 2006-02-12)
 --------------------------------------
index eaae6db..839c62c 100644 (file)
@@ -405,8 +405,25 @@ if (!empty($compose_messages[$session])) {
 // should never directly manipulate an object like this
 if (!empty($attachments)) {
     $attachments = unserialize(urldecode($attachments));
-    if (!empty($attachments) && is_array($attachments))
-        $composeMessage->entities = $attachments;
+    if (!empty($attachments) && is_array($attachments)) {
+        // sanitize the "att_local_name" since it is user-supplied and used to access the file system
+        // it must be alpha-numeric and 32 characters long (see the use of GenerateRandomString() below)
+        foreach ($attachments as $i => $attachment) {
+            if (empty($attachment->att_local_name) || strlen($attachment->att_local_name) !== 32) {
+                unset($attachments[$i]);
+                continue;
+            }
+            // probably marginal difference between (ctype_alnum + function_exists) and preg_match
+            if (function_exists('ctype_alnum')) {
+                if (!ctype_alnum($attachment->att_local_name))
+                    unset($attachments[$i]);
+            }
+            else if (preg_match('/[^0-9a-zA-Z]/', $attachment->att_local_name))
+                unset($attachments[$i]);
+        }
+        if (!empty($attachments))
+            $composeMessage->entities = $attachments;
+    }
 }
 
 if (empty($mailbox)) {