CVE-2021-4283: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: A vulnerability was found in FreeBPX voicemail. It has been rated as problematic. Affected by this issue is some unknown functionality of the file views/ssettings.php of the component Settings Handler. The manipulation of the argument key leads to cross site scripting. The attack may be launched remotely. Upgrading to version 14.0.6.25 is able to address this issue. The name of the patch is ffce4882016076acd16fe0f676246905aa3cb2f3. It is recommended to upgrade the affected component. The identifier of this vulnerability is VDB-216872.
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: 2022-12-27T10:15Z
Repository: https://github.com/FreePBX/voicemail
Language: PHP
Files changed: page.voicemail.php, views/ssettings.php
Commit date: 2021-09-15 06:50:54 +0000
Commit message: FREEI-2107--stored-xss

Diff: diff --git a/page.voicemail.php b/page.voicemail.php
index ff2a3f7..31b70e8 100644
--- a/page.voicemail.php
+++ b/page.voicemail.php
@@ -396,11 +396,12 @@ show_view(dirname(__FILE__).'/views/header.php',array(
 		)
 );
 //TODO: Do we really need to say "UPDATE COMPLETED??"
 if ($need_update && $action != 'usage') {
 	$args = array();
-	if (voicemail_update_settings($action, $context, $extension, $_REQUEST)) {
+	$request = freepbxGetSanitizedRequest(FILTER_UNSAFE_RAW);
+	if (voicemail_update_settings($action, $context, $extension, $request)) {
 		$url = "config.php?type=$type&display=$display&action=$action&ext=$extension&updated=true";
 				needreload();
 				redirect($url);
 	} else {
 		$url = "config.php?type=$type&display=$display&action=$action&ext=$extension&updated=false";
@@ -678,11 +679,12 @@ switch ($action) {
 		/* Usage information and options available for system-wide,
 			 and individual account views.
 		*/
 		$scope = voicemail_get_scope($extension);
 		if ($need_update) {
-			voicemail_update_usage($vmail_info, $context, $extension, $_REQUEST);
+			$request = freepbxGetSanitizedRequest(FILTER_UNSAFE_RAW);
+			voicemail_update_usage($vmail_info, $context, $extension, $request);
 			if (!empty($extension)) {
 				$url = "config.php?display=$display&ext=$extension&action=$action&updated=true";
 			} else {
 				$url = "config.php?display=$display&action=$action&updated=true";
 			}
diff --git a/views/ssettings.php b/views/ssettings.php
index 46d1ac7..74b7617 100644
--- a/views/ssettings.php
+++ b/views/ssettings.php
@@ -37,14 +37,14 @@
 											<i class="fa fa-question-circle fpbx-help-icon" data-for="<?php echo $id_prefix?>__<?php echo $key?>"></i>
 										</div>
 										<div class="col-md-9">
 											<?php switch($items['type']) {
 														case "number": ?>
-														<input type="number" class="form-control" id="<?php echo $id_prefix?>__<?php echo $key?>" name="<?php echo $id_prefix?>__<?php echo $key?>" value="<?php echo !empty($settings[$key]) ? $settings[$key] : $items['default'] ?>" <?php if(!empty($items['options'])) {?>min="<?php echo $items['options'][0]?>" max="<?php echo $items['options'][1]?>"<?php } ?>>
+														<input type="number" class="form-control" id="<?php echo $id_prefix?>__<?php echo $key?>" name="<?php echo $id_prefix?>__<?php echo $key?>" value="<?php echo !empty($settings[$key]) ? htmlentities($settings[$key], ENT_COMPAT, 'UTF-8') : $items['default'] ?>" <?php if(!empty($items['options'])) {?>min="<?php echo $items['options'][0]?>" max="<?php echo $items['options'][1]?>"<?php } ?>>
 												<?php break;
 														case "text": ?>
-														<input type="text" class="form-control" id="<?php echo $id_prefix?>__<?php echo $key?>" name="<?php echo $id_prefix?>__<?php echo $key?>" value="<?php echo !empty($settings[$key]) ? $settings[$key] : $items['default'] ?>">
+														<input type="text" class="form-control" id="<?php echo $id_prefix?>__<?php echo $key?>" name="<?php echo $id_prefix?>__<?php echo $key?>" value="<?php echo !empty($settings[$key]) ? htmlentities($settings[$key], ENT_COMPAT, 'UTF-8') : $items['default'] ?>">
 												<?php break;
 														case "textbox":
 															$value = !empty($settings[$key]) ? $settings[$key] : $items['default'];
 															$value = str_replace(array("\\n","\\t","\\r"),array("\n","\t","\r"),$value);
 												?>

Vulnerable code: 	if (voicemail_update_settings($action, $context, $extension, $_REQUEST)) {
			voicemail_update_usage($vmail_info, $context, $extension, $_REQUEST);
														<input type="number" class="form-control" id="<?php echo $id_prefix?>__<?php echo $key?>" name="<?php echo $id_prefix?>__<?php echo $key?>" value="<?php echo !empty($settings[$key]) ? $settings[$key] : $items['default'] ?>" <?php if(!empty($items['options'])) {?>min="<?php echo $items['options'][0]?>" max="<?php echo $items['options'][1]?>"<?php } ?>>
														<input type="text" class="form-control" id="<?php echo $id_prefix?>__<?php echo $key?>" name="<?php echo $id_prefix?>__<?php echo $key?>" value="<?php echo !empty($settings[$key]) ? $settings[$key] : $items['default'] ?>">
Fixed code: 	$request = freepbxGetSanitizedRequest(FILTER_UNSAFE_RAW);
	if (voicemail_update_settings($action, $context, $extension, $request)) {
			$request = freepbxGetSanitizedRequest(FILTER_UNSAFE_RAW);
			voicemail_update_usage($vmail_info, $context, $extension, $request);
														<input type="number" class="form-control" id="<?php echo $id_prefix?>__<?php echo $key?>" name="<?php echo $id_prefix?>__<?php echo $key?>" value="<?php echo !empty($settings[$key]) ? htmlentities($settings[$key], ENT_COMPAT, 'UTF-8') : $items['default'] ?>" <?php if(!empty($items['options'])) {?>min="<?php echo $items['options'][0]?>" max="<?php echo $items['options'][1]?>"<?php } ?>>
														<input type="text" class="form-control" id="<?php echo $id_prefix?>__<?php echo $key?>" name="<?php echo $id_prefix?>__<?php echo $key?>" value="<?php echo !empty($settings[$key]) ? htmlentities($settings[$key], ENT_COMPAT, 'UTF-8') : $items['default'] ?>">