CVE-2018-16974 (published 2018-09-12T21:29Z)

An issue was discovered in Elefant CMS before 2.0.7. There is a PHP Code Execution Vulnerability in apps/filemanager/upload/drop.php by using /filemanager/api/rm/.htaccess to remove the .htaccess file, and then using a filename that ends in .php followed by space characters (for bypassing the blacklist).

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
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/jbroadway/elefant
commit_details: repo_url: https://github.com/jbroadway/elefant
author: lux
author_date: 2018-09-11 02:13:26-05:00
msg: Fixed filemanager file upload validations, re: #287
repository: repo_url: https://github.com/jbroadway/elefant
repo_name: jbroadway/elefant
description: Elefant, the refreshingly simple PHP CMS and web framework.
repo_language: PHP
owner: jbroadway
file_changes: filename: embed.php
change_type: ModificationType.MODIFY
diff: @@ -110,7 +110,9 @@ switch ($_GET['action']) {
 			return;
 		}
 		
-		if (preg_match ('/\.(php|phtml|pht|php3|php4|php5|phar|js|rb|py|pl|sh|bash|exe)$/i', $_POST['newName'])) {
+		$_POST['newName'] = trim ($_POST['newName']);
+		
+		if (preg_match ('/\.(php|phtml|pht|php3|php4|php5|phar|js|rb|py|pl|sh|bash|exe|htaccess|htpasswd)$/i', $_POST['newName'])) {
 			echo __ ('Invalid file type');
 			return;
 		}

programming_language: PHP
filename: upload.php
change_type: ModificationType.MODIFY
diff: @@ -41,9 +41,9 @@ foreach ($_FILES['file']['error'] as $error) {
 }
 
 // some browsers may urlencode the file name
-$_FILES['file']['name'] = urldecode ($_FILES['file']['name']);
+$_FILES['file']['name'] = trim (urldecode ($_FILES['file']['name']));
 
-if (preg_match ('/\.(php|phtml|pht|php3|php4|php5|phar|js|rb|py|pl|sh|bash|exe)$/i', $_FILES['file']['name'])) {
+if (preg_match ('/\.(php|phtml|pht|php3|php4|php5|phar|js|rb|py|pl|sh|bash|exe|htaccess|htpasswd)$/i', $_FILES['file']['name'])) {
 	echo json_encode (array ('error' => __ ('Cannot upload executable files due to security.')));
 	return;
 }

programming_language: PHP
filename: upload.php
change_type: ModificationType.MODIFY
diff: @@ -49,7 +49,7 @@ foreach ($_FILES['file']['error'] as $error) {
 }
 
 for ($i = 0; $i < count ($_FILES['file']['name']); $i++) {
-	$_FILES['file']['name'][$i] = urldecode ($_FILES['file']['name'][$i]);
+	$_FILES['file']['name'][$i] = trim (urldecode ($_FILES['file']['name'][$i]));
 	if (@file_exists ($root . $_POST['path'] . '/' . $_FILES['file']['name'][$i])) {
 		$page->title = __ ('File Already Exists') . ': ' . $_FILES['file']['name'][$i];
 		echo '<p>' . __ ('A file by that name already exists.') . '</p>';
@@ -62,7 +62,7 @@ for ($i = 0; $i < count ($_FILES['file']['name']); $i++) {
 		echo '<p><a href="/filemanager">' . __ ('Back') . '</a></p>';
 		return;
 	}
-	if (preg_match ('/\.(php|phtml|pht|php3|php4|php5|phar|js|rb|py|pl|sh|bash|exe)$/i', $_FILES['file']['name'][$i])) {
+	if (preg_match ('/\.(php|phtml|pht|php3|php4|php5|phar|js|rb|py|pl|sh|bash|exe|htaccess|htpasswd)$/i', $_FILES['file']['name'][$i])) {
 		$page->title = __ ('Invalid File Name') . ': ' . $_FILES['file']['name'][$i];
 		echo '<p>' . __ ('Cannot upload executable files due to security.') . '</p>';
 		echo '<p><a href="/filemanager">' . __ ('Back') . '</a></p>';

programming_language: PHP
filename: drop.php
change_type: ModificationType.MODIFY
diff: @@ -45,9 +45,9 @@ if (isset ($_FILES['file']['error']) && $_FILES['file']['error'] > 0) {
 }
 
 // some browsers may urlencode the file name
-$_FILES['file']['name'] = urldecode ($_FILES['file']['name']);
+$_FILES['file']['name'] = trim (urldecode ($_FILES['file']['name']));
 
-if (preg_match ('/\.(php|phtml|pht|php3|php4|php5|phar|js|rb|py|pl|sh|bash|exe)$/i', $_FILES['file']['name'])) {
+if (preg_match ('/\.(php|phtml|pht|php3|php4|php5|phar|js|rb|py|pl|sh|bash|exe|htaccess|htpasswd)$/i', $_FILES['file']['name'])) {
 	echo json_encode (array ('success' => false, 'error' => __ ('Cannot upload executable files due to security.')));
 	return;
 }

programming_language: PHP
filename: API.php
change_type: ModificationType.MODIFY
diff: @@ -13,7 +13,7 @@ class API extends Restful {
 	 * Handle list directory requests (/filemanager/api/ls).
 	 */
 	public function get_ls () {
-		$file = urldecode (join ('/', func_get_args ()));
+		$file = trim (urldecode (join ('/', func_get_args ())));
 
 		$res = FileManager::dir ($file);
 		if (! $res) {
@@ -43,7 +43,7 @@ class API extends Restful {
 	 * Handle Bitly link requests (/filemanager/api/bitly).
 	 */
 	public function get_bitly () {
-		$file = urldecode (join ('/', func_get_args ()));
+		$file = trim (urldecode (join ('/', func_get_args ())));
 		$link = $this->controller->absolutize ('/files/' . $file);
 		return BitlyLink::lookup ($link);
 	}
@@ -52,7 +52,7 @@ class API extends Restful {
 	 * Handle remove file requests (/filemanager/api/rm).
 	 */
 	public function post_rm () {
-		$file = urldecode (join ('/', func_get_args ()));
+		$file = trim (urldecode (join ('/', func_get_args ())));
 
 		$res = FileManager::unlink ($file);
 		if (! $res) {
@@ -71,7 +71,7 @@ class API extends Restful {
 	 * Note: Erases the contents of the folder as well.
 	 */
 	public function post_rmdir () {
-		$file = urldecode (join ('/', func_get_args ()));
+		$file = trim (urldecode (join ('/', func_get_args ())));
 
 		$res = FileManager::rmdir ($file, true);
 		if (! $res) {
@@ -89,7 +89,7 @@ class API extends Restful {
 	 * Handle rename requests (/filemanager/api/mv).
 	 */
 	public function post_mv () {
-		$file = urldecode (join ('/', func_get_args ()));
+		$file = trim (urldecode (join ('/', func_get_args ())));
 
 		$is_folder = FileManager::verify_folder ($file) ? true : false;
 		
@@ -114,7 +114,7 @@ class API extends Restful {
 	 * folders.
 	 */
 	public function post_drop () {
-		$file = urldecode (join ('/', func_get_args ()));
+		$file = trim (urldecode (join ('/', func_get_args ())));
 		
 		if (! FileManager::move ($file, $_POST['folder'])) {
 			return $this->error (FileManager::error ());
@@ -133,7 +133,7 @@ class API extends Restful {
 	 * Handle make directory requests (/filemanager/api/mkdir).
 	 */
 	public function post_mkdir () {
-		$file = urldecode (join ('/', func_get_args ()));
+		$file = trim (urldecode (join ('/', func_get_args ())));
 		
 		if (! FileManager::mkdir ($file)) {
 			return $this->error (FileManager::error ());
@@ -153,7 +153,7 @@ class API extends Restful {
 	 * be used to set an individual property's value.
 	 */
 	public function post_prop () {
-		$file = urldecode (join ('/', func_get_args ()));
+		$file = trim (urldecode (join ('/', func_get_args ())));
 		if (! FileManager::verify_file ($file)) {
 			return $this->error (__ ('Invalid file name'));
 		}
@@ -200,7 +200,7 @@ class API extends Restful {
 	 * Handle unzip requests via (/filemanager/api/unzip).
 	 */
 	public function post_unzip () {
-		$file = urldecode (join ('/', func_get_args ()));
+		$file = trim (urldecode (join ('/', func_get_args ())));
 		if (! FileManager::verify_file ($file)) {
 			return $this->error (__ ('Invalid file name'));
 		}

programming_language: PHP
filename: FileManager.php
change_type: ModificationType.MODIFY
diff: @@ -160,6 +160,9 @@ class FileManager {
 		} elseif (! self::verify_file ($file)) {
 			self::$error = __ ('File not found');
 			return false;
+		} elseif (! self::verify_file_name ($file)) {
+			self::$error = __ ('Invalid file name');
+			return false;
 		} elseif (! unlink (self::root () . $file)) {
 			self::$error = __ ('Unable to delete') . ' ' . $file;
 			return false;
@@ -405,7 +408,7 @@ class FileManager {
 		if (! preg_match ('/^[a-zA-Z0-9 _-]+\.[a-zA-Z0-9_-]+$/', $name)) {
 			return false;
 		}
-		if (preg_match ('/\.php$/i', $name)) {
+		if (preg_match ('/\.(php|phtml|pht|php3|php4|php5|phar|js|rb|py|pl|sh|bash|exe|htaccess|htpasswd)$/i', $name)) {
 			return false;
 		}
 		return true;

programming_language: PHP