CVE-2021-44664 (published 2022-02-24T21:15Z)

An Authenticated Remote Code Exection (RCE) vulnerability exists in Xerte through 3.9 in website_code/php/import/fileupload.php by uploading a maliciously crafted PHP file though the project interface disguised as a language file to bypasses the upload filters. Attackers can manipulate the files destination by abusing path traversal in the 'mediapath' variable.

Severity: MEDIUM
CVSS v2 base score: 6.5 (AV:N/AC:L/Au:S/C:P/I:P/A:P)
CVSS v3 base score: 8.8, HIGH (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-22
cwe_name: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
description: The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
extended_description: 
            Many file operations are intended to take place within a restricted directory. By using special elements such as ".." and "/" separators, attackers can escape outside of the restricted location to access files or directories that are elsewhere on the system. One of the most common special elements is the "../" sequence, which in most modern operating systems is interpreted as the parent directory of the current location. This is referred to as relative path traversal. Path traversal also covers the use of absolute pathnames such as "/usr/local/bin" to access unexpected files. This is referred to as absolute path traversal.
         
         
cwe_id: CWE-434
cwe_name: Unrestricted Upload of File with Dangerous Type
description: The product allows the upload or transfer of dangerous file types that are automatically processed within its environment.
extended_description: 
            
            
            
            
            
         
         

Fix information:
repo_url: https://github.com/thexerteproject/xerteonlinetoolkits
commit_details: repo_url: https://github.com/thexerteproject/xerteonlinetoolkits
author: Tom Reijnders
author_date: 2021-05-07 16:59:18+02:00
msg: Prohibit path traversal on upload

 - Thank you Rik Lutz
repository: repo_url: https://github.com/thexerteproject/xerteonlinetoolkits
repo_name: thexerteproject/xerteonlinetoolkits
description: Xerte Online Toolkits
repo_language: JavaScript
owner: thexerteproject
file_changes: filename: connector.php
change_type: ModificationType.MODIFY
diff: @@ -39,7 +39,7 @@ if (!isset($_SESSION['toolkits_logon_id'])){
 $rootpath = $_REQUEST['uploadDir'];
 $rooturl = $_REQUEST['uploadURL'];
 
-if (strpos($rootpath, 'USER-FILES') === false || strpos($rooturl, 'USER-FILES') === false)
+if (strpos($rootpath, 'USER-FILES') === false  || strpos($rootpath, '../') !== false || strpos($rooturl, 'USER-FILES') === false)
 {
     die("Invalid upload location");
 }

programming_language: PHP
filename: uploadImage.php
change_type: ModificationType.MODIFY
diff: @@ -72,7 +72,7 @@ if (!isset($_FILES['upload']))
 }
 
 // Check upload path, should contain USER-FILES
-if (strpos($_REQUEST['uploadURL'], 'USER-FILES') === false)
+if (strpos($_REQUEST['uploadPath'], 'USER-FILES') === false || strpos($_REQUEST['uploadPath'], '../') !== false || strpos($_REQUEST['uploadURL'], 'USER-FILES') === false)
 {
     // Invalid folder, reject!
     $response->uploaded = 0;

programming_language: PHP
filename: upload.php
change_type: ModificationType.MODIFY
diff: @@ -96,7 +96,7 @@ if (strpos($_FILES['Filedata']['name'], '../') !== false)
     $pass = false;
 if (strpos($_FILES['Filedata']['name'], '...') !== false)
     $pass = false;
-if (strpos($_GET['path'], 'USER-FILES') === false)
+if (strpos($_GET['path'], 'USER-FILES') === false || strpos($_GET['path'], '../') !== false)
     $pass = false;
 
 if ($pass === false) {

programming_language: PHP
filename: upload.php
change_type: ModificationType.MODIFY
diff: @@ -79,7 +79,7 @@ if (strpos($_FILES['Filedata']['name'], '../') !== false)
     $pass = false;
 if (strpos($_FILES['Filedata']['name'], '...') !== false)
     $pass = false;
-if (strpos($_GET['path'], 'USER-FILES') === false)
+if (strpos($_GET['path'], 'USER-FILES') === false || strpos($_GET['path'], '../') !== false)
     $pass = false;
 
 if ($pass === false) {

programming_language: PHP
filename: fileupload.php
change_type: ModificationType.MODIFY
diff: @@ -55,7 +55,7 @@ if (!isset($_SESSION['toolkits_logon_username']))
     _debug("Session is invalid or expired");
     die("Session is invalid or expired");
 }
-if (strpos($_POST['mediapath'], 'USER-FILES') === false)
+if (strpos($_POST['mediapath'], 'USER-FILES') === false || strpos($_POST['mediapath'], '../') !== false)
 {
     // Invalid upload path
     _debug("Invalid or illegal mediapath");

programming_language: PHP
repo_url: https://github.com/thexerteproject/xerteonlinetoolkits
commit_details: repo_url: https://github.com/thexerteproject/xerteonlinetoolkits
author: Tom Reijnders
author_date: 2021-03-22 21:58:29+01:00
msg: Security! Check and verify paths used by move_uploaded_file

 - Make sure uploaded files can only be saved in the USER-FILES
   subfolder
repository: repo_url: https://github.com/thexerteproject/xerteonlinetoolkits
repo_name: thexerteproject/xerteonlinetoolkits
description: Xerte Online Toolkits
repo_language: JavaScript
owner: thexerteproject
file_changes: filename: uploadImage.php
change_type: ModificationType.MODIFY
diff: @@ -71,6 +71,17 @@ if (!isset($_FILES['upload']))
     exit(-1);
 }
 
+// Check upload path, should contain USER-FILES
+if (strpos($_REQUEST['uploadURL'], 'USER-FILES') === false)
+{
+    // Invalid folder, reject!
+    $response->uploaded = 0;
+    $response->error = IMAGEUPOLOAD_NOT_UPLOADED;
+
+    echo json_encode($response);
+    exit(-1);
+}
+
 if (isset($_FILES['upload']['error']) && $_FILES['upload']['error'] != 0)
 {
     switch($_FILES['upload']['error']) {

programming_language: PHP
filename: upload.php
change_type: ModificationType.MODIFY
diff: @@ -96,6 +96,8 @@ if (strpos($_FILES['Filedata']['name'], '../') !== false)
     $pass = false;
 if (strpos($_FILES['Filedata']['name'], '...') !== false)
     $pass = false;
+if (strpos($_GET['path'], 'USER-FILES') === false)
+    $pass = false;
 
 if ($pass === false) {
     receive_message($_SESSION['toolkits_logon_username'], "UPLOAD", "CRITICAL", "Invalid filename: " . $_FILES['Filedata']['name'], "Invalid filename: " . $_FILES['Filedata']['name']);

programming_language: PHP
filename: upload.php
change_type: ModificationType.MODIFY
diff: @@ -79,6 +79,8 @@ if (strpos($_FILES['Filedata']['name'], '../') !== false)
     $pass = false;
 if (strpos($_FILES['Filedata']['name'], '...') !== false)
     $pass = false;
+if (strpos($_GET['path'], 'USER-FILES') === false)
+    $pass = false;
 
 if ($pass === false) {
     receive_message($_SESSION['toolkits_logon_username'], "UPLOAD", "CRITICAL", "Invalid filename: " . $_FILES['Filedata']['name'], "Invalid filename: " . $_FILES['Filedata']['name']);

programming_language: PHP
filename: fileupload.php
change_type: ModificationType.MODIFY
diff: @@ -55,6 +55,12 @@ if (!isset($_SESSION['toolkits_logon_username']))
     _debug("Session is invalid or expired");
     die("Session is invalid or expired");
 }
+if (strpos($_POST['mediapath'], 'USER-FILES') === false)
+{
+    // Invalid upload path
+    _debug("Invalid or illegal mediapath");
+    die("Invalid or illegal mediapath");
+}
 
 _load_language_file("/website_code/php/import/fileupload.inc");
 

programming_language: PHP