CVE-2020-21487: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Cross Site Scripting vulnerability found in Netgate pfSense 2.4.4 and ACME package v.0.6.3 allows attackers to execute arbitrary code via the RootFolder field of acme_certificates.php.
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: 9.6
Published: 2023-04-04T15:15Z
Repository: https://github.com/pfsense/FreeBSD-ports
Language: PHP
Files changed: security/pfSense-pkg-acme/Makefile, security/pfSense-pkg-acme/files/usr/local/pkg/acme/acme_sh.inc, security/pfSense-pkg-acme/files/usr/local/www/acme/acme_accountkeys.php, security/pfSense-pkg-acme/files/usr/local/www/acme/acme_certificates.php
Commit date: 2019-11-08 10:43:32 -0500
Commit message: Prevent ACME output from being interpreted as HTML. Fixes #9888

Diff: diff --git a/security/pfSense-pkg-acme/Makefile b/security/pfSense-pkg-acme/Makefile
index 2eff47513887f..8cca6d632f9c2 100644
--- a/security/pfSense-pkg-acme/Makefile
+++ b/security/pfSense-pkg-acme/Makefile
@@ -1,9 +1,10 @@
 # $FreeBSD$
 
 PORTNAME=	pfSense-pkg-acme
 PORTVERSION=	0.6.3
+PORTREVISION=	1
 CATEGORIES=	security
 MASTER_SITES=	# empty
 DISTFILES=	# empty
 EXTRACT_ONLY=	# empty
 
diff --git a/security/pfSense-pkg-acme/files/usr/local/pkg/acme/acme_sh.inc b/security/pfSense-pkg-acme/files/usr/local/pkg/acme/acme_sh.inc
index 839adda7f3f1d..185a105125549 100644
--- a/security/pfSense-pkg-acme/files/usr/local/pkg/acme/acme_sh.inc
+++ b/security/pfSense-pkg-acme/files/usr/local/pkg/acme/acme_sh.inc
@@ -60,11 +60,11 @@ class acme_sh {
 	public $ocspstaple;
 	
 	private function execacmesh($command, $envvariables = null) {
 		$command = "/usr/local/pkg/acme/acme.sh " . $command;
 		if ($this->debug) {
-			echo "<br/>\n".$command."<br/>\n";
+			echo "\n{$command}\n";
 		}
 		// add to cron environment path: /usr/local/bin/
 		$env = array();
 		$env['path'] = "/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin/";
 		$env['PATH'] = "/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin/";
diff --git a/security/pfSense-pkg-acme/files/usr/local/www/acme/acme_accountkeys.php b/security/pfSense-pkg-acme/files/usr/local/www/acme/acme_accountkeys.php
index f293fac5e293e..6cce56a63809c 100644
--- a/security/pfSense-pkg-acme/files/usr/local/www/acme/acme_accountkeys.php
+++ b/security/pfSense-pkg-acme/files/usr/local/www/acme/acme_accountkeys.php
@@ -130,11 +130,11 @@ echo "</div>";
 ?>
 <div id="renewoutputbox" class="alert alert-success clearfix hidden" role="alert">
 	<button type="button" class="close" data-dismiss="alert" aria-label="Close">
 		<span aria-hidden="true">×</span>
 	</button>
-	<div id="renewoutput" class="pull-left">
+	<div id="renewoutput" class="pull-left" style="white-space: pre-wrap">
 	</div>
 </div>
 
 <?php
 display_top_tabs_active($acme_tab_array['acme'], "accountkeys");
@@ -217,11 +217,11 @@ function set_content(elementid, image) {
 	item.innerHTML = image;
 }
 
 function js_callbackrenew(data) {
 	$('#renewoutputbox').removeClass("hidden");
-	$('#renewoutput').html(data);
+	$('#renewoutput').text(data);
 }
 
 function js_callback(req_content) {
 	
 	showapplysettings.style.display = 'block';
diff --git a/security/pfSense-pkg-acme/files/usr/local/www/acme/acme_certificates.php b/security/pfSense-pkg-acme/files/usr/local/www/acme/acme_certificates.php
index f44830a83a94a..feba8045ad6a2 100644
--- a/security/pfSense-pkg-acme/files/usr/local/www/acme/acme_certificates.php
+++ b/security/pfSense-pkg-acme/files/usr/local/www/acme/acme_certificates.php
@@ -154,11 +154,11 @@ echo "</div>";
 ?>
 <div id="renewoutputbox" class="alert alert-success clearfix hidden" role="alert">
 	<button type="button" class="close" data-dismiss="alert" aria-label="Close">
 		<span aria-hidden="true">×</span>
 	</button>
-	<div id="renewoutput" class="pull-left">
+	<div id="renewoutput" class="pull-left" style="white-space: pre-wrap">
 	</div>
 </div>
 	
 <?php
 display_top_tabs_active($acme_tab_array['acme'], "certificates");
@@ -324,11 +324,11 @@ function set_content(elementid, image) {
 	item.innerHTML = image;
 }
 
 function js_callbackrenew(data) {
 	$('#renewoutputbox').removeClass("hidden");
-	$('#renewoutput').html(data.replace(/(?:\r\n|\r|\n)/g, '<br />'));
+	$('#renewoutput').text(data);
 }
 
 function js_callback(req_content) {
 	
 	if(req_content !== '') {

Vulnerable code: 			echo "<br/>\n".$command."<br/>\n";
	<div id="renewoutput" class="pull-left">
	$('#renewoutput').html(data);
	<div id="renewoutput" class="pull-left">
	$('#renewoutput').html(data.replace(/(?:\r\n|\r|\n)/g, '<br />'));
Fixed code: PORTREVISION=	1
			echo "\n{$command}\n";
	<div id="renewoutput" class="pull-left" style="white-space: pre-wrap">
	$('#renewoutput').text(data);
	<div id="renewoutput" class="pull-left" style="white-space: pre-wrap">
	$('#renewoutput').text(data);