CVE-2024-22418: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Group-Office is an enterprise CRM and groupware tool. Affected versions are subject to a vulnerability which is present in the file upload mechanism of Group Office. It allows an attacker to execute arbitrary JavaScript code by embedding it within a file's name. For instance, using a filename such as “><img src=x onerror=prompt('XSS')>.jpg” triggers the vulnerability. When this file is uploaded, the JavaScript code within the filename is executed. This issue has been addressed in version 6.8.29. All users are advised to upgrade. There are no known workarounds for this vulnerability.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 5.4
Published: 2024-01-18T21:15Z
Repository: https://github.com/Intermesh/groupoffice
Language: PHP
Files changed: www/modules/files/controller/FileController.php, www/modules/files/controller/FolderController.php
Commit date: 2024-01-11 10:22:02 +0100
Commit message: Files: Fixed Stored XSS Vulnerability via Malicious File Names in Upload Feature

Diff: diff --git a/www/modules/files/controller/FileController.php b/www/modules/files/controller/FileController.php
index ba64906cfe..3e28697aaa 100644
--- a/www/modules/files/controller/FileController.php
+++ b/www/modules/files/controller/FileController.php
@@ -187,11 +187,11 @@ class FileController extends \GO\Base\Controller\AbstractModelController {
 		return $count > 1;
 	}
 	
 	protected function afterDisplay(&$response, &$model, &$params) {
 
-		$response['data']['path'] = $model->path;
+		$response['data']['path'] = htmlspecialchars($model->path);
 		$response['data']['size'] = $model->fsFile->size();
 		$response['data']['extension'] = strtolower($model->fsFile->extension());
 		$response['data']['type'] = \GO::t($response['data']['extension'], 'base', 'filetypes');
 		
 		$response['data']['locked_user_name']=$model->lockedByUser ? $model->lockedByUser->name : '';
diff --git a/www/modules/files/controller/FolderController.php b/www/modules/files/controller/FolderController.php
index 1f07f2fe74..0e76564498 100644
--- a/www/modules/files/controller/FolderController.php
+++ b/www/modules/files/controller/FolderController.php
@@ -752,11 +752,11 @@ class FolderController extends \GO\Base\Controller\AbstractModelController {
 
 		if(empty($params['skip_fs_sync']) && empty(GO::config()->files_disable_filesystem_sync))
 			$folder->checkFsSync();
 
 		//useful information for the view.
-		$response['path'] = $folder->path;
+		$response['path'] = htmlentities($folder->path);
 
 		//Show this page in thumbnails or list
 		$folderPreference = \GO\Files\Model\FolderPreference::model()->findByPk(array('user_id'=>\GO::user()->id,'folder_id'=>$folder->id));
 		if($folderPreference)
 			$response['thumbs']=$folderPreference->thumbs;
@@ -982,11 +982,11 @@ class FolderController extends \GO\Base\Controller\AbstractModelController {
 		return $response;
 	}
         
 	public function formatListRecord($record, $model) {
 
-		$record['path'] = $model->path;
+		$record['path'] = htmlspecialchars($model->path);
 
 		if ($model instanceof Folder) {
 			$record['type_id'] = 'd:' . $model->id;
 			$record['type'] = \GO::t("Folder", "files");
 			$record['size'] = '-';

Vulnerable code: 		$response['data']['path'] = $model->path;
		$response['path'] = $folder->path;
		$record['path'] = $model->path;
Fixed code: 		$response['data']['path'] = htmlspecialchars($model->path);
		$response['path'] = htmlentities($folder->path);
		$record['path'] = htmlspecialchars($model->path);