Vulnerability: /usr/local/www/pkg.php in pfSense CE before 2.6.0 and pfSense Plus before 22.01 uses $_REQUEST['pkg_filter'] in a PHP echo call, causing XSS.
Vulnerability ID: CVE-2022-23993
CWE: CWE-79
Severity score: 2.9
Project: https://github.com/pfsense/pfsense
Published: 2022-01-26
File: src/usr/local/www/pkg.php
Commit message: Clean up pkg filter text before use. Fixes #12725

Also remove unnecessary echos of the value.
Commit author: jim-p

Vulnerable version (before fix):
 function save_changes_to_xml(xml) { 									if ($sf['name'] == $_REQUEST['pkg_filter_type']) { 										$filter_fieldname = $sf['fieldname']; 										#Use a default regex on sortable fields when none is declared 										if ($sf['regex']) { 											$filter_regex = str_replace("%FILTERTEXT%", $_REQUEST['pkg_filter'], trim($sf['regex'])); 										} else { 											$filter_regex = "/{$_REQUEST['pkg_filter']}/i"; 										} 									} 								} function save_changes_to_xml(xml) { 						$fieldname = $ip[xml_safe_fieldname($column['fieldname'])]; 						if ($column['fieldname'] == $filter_fieldname) { 							if ($filter_regex) { 								//echo "$filter_regex - $fieldname<p/>"; 								preg_match($filter_regex, $fieldname, $filter_matches); 								break; 							} function save_changes_to_xml(xml) {  </form> <?php echo "<!-- filter_fieldname: {$filter_fieldname} -->"; echo "<!-- filter_regex: {$filter_regex} -->";  include("foot.inc"); ?>

Fixed version (after fix):
 function save_changes_to_xml(xml) { 									if ($sf['name'] == $_REQUEST['pkg_filter_type']) { 										$filter_fieldname = $sf['fieldname']; 										#Use a default regex on sortable fields when none is declared 										$pkg_filter = cleanup_regex_pattern(htmlspecialchars(strip_tags($_REQUEST['pkg_filter']))); 										if ($sf['regex']) { 											$filter_regex = str_replace("%FILTERTEXT%", $pkg_filter, trim($sf['regex'])); 										} else { 											$filter_regex = "/{$pkg_filter}/i"; 										} 									} 								} function save_changes_to_xml(xml) { 						$fieldname = $ip[xml_safe_fieldname($column['fieldname'])]; 						if ($column['fieldname'] == $filter_fieldname) { 							if ($filter_regex) { 								preg_match($filter_regex, $fieldname, $filter_matches); 								break; 							} function save_changes_to_xml(xml) {  </form> <?php include("foot.inc"); ?>

Patch:
patch: @@ -434,10 +434,11 @@ function save_changes_to_xml(xml) {
 									if ($sf['name'] == $_REQUEST['pkg_filter_type']) {
 										$filter_fieldname = $sf['fieldname'];
 										#Use a default regex on sortable fields when none is declared
+										$pkg_filter = cleanup_regex_pattern(htmlspecialchars(strip_tags($_REQUEST['pkg_filter'])));
 										if ($sf['regex']) {
-											$filter_regex = str_replace("%FILTERTEXT%", $_REQUEST['pkg_filter'], trim($sf['regex']));
+											$filter_regex = str_replace("%FILTERTEXT%", $pkg_filter, trim($sf['regex']));
 										} else {
-											$filter_regex = "/{$_REQUEST['pkg_filter']}/i";
+											$filter_regex = "/{$pkg_filter}/i";
 										}
 									}
 								}
@@ -452,7 +453,6 @@ function save_changes_to_xml(xml) {
 						$fieldname = $ip[xml_safe_fieldname($column['fieldname'])];
 						if ($column['fieldname'] == $filter_fieldname) {
 							if ($filter_regex) {
-								//echo "$filter_regex - $fieldname<p/>";
 								preg_match($filter_regex, $fieldname, $filter_matches);
 								break;
 							}
@@ -603,7 +603,4 @@ function save_changes_to_xml(xml) {
 
 </form>
 <?php
-echo "<!-- filter_fieldname: {$filter_fieldname} -->";
-echo "<!-- filter_regex: {$filter_regex} -->";
-
 include("foot.inc"); ?>
path: src/usr/local/www/pkg.php