CVE-2022-3844: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: A vulnerability, which was classified as problematic, was found in Webmin 2.001. Affected is an unknown function of the file xterm/index.cgi. The manipulation leads to basic cross site scripting. It is possible to launch the attack remotely. Upgrading to version 2.003 is able to address this issue. The patch is identified as d3d33af3c0c3fd3a889c84e287a038b7a457d811. It is recommended to upgrade the affected component. VDB-212862 is the identifier assigned to 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: 6.1
Published: 2022-11-02T20:15Z
Repository: https://github.com/webmin/webmin
Language: Other
Files changed: xterm/index.cgi
Commit date: 2022-10-30 15:55:21 -0700
Commit message: Clean up code and prevent HTML attacks on untrusted inputs

Diff: diff --git a/xterm/index.cgi b/xterm/index.cgi
index 4a3fef7a11..825a39de2b 100644
--- a/xterm/index.cgi
+++ b/xterm/index.cgi
@@ -169,36 +169,30 @@ my $wspath = "/$module_name/ws-".$port;
 $miniserv{'websockets_'.$wspath} = "host=127.0.0.1 port=$port wspath=/ user=$remote_user";
 &put_miniserv_config(\%miniserv);
 &unlock_file(&get_miniserv_config_file());
 &reload_miniserv();
 
-# Launch the shell server on that port
-&foreign_require("cron");
-my $shellserver_cmd = "$module_config_directory/shellserver.pl";
-if (!-r $shellserver_cmd) {
-	&cron::create_wrapper($shellserver_cmd, $module_name, "shellserver.pl");
-	}
+# Check permissions for user to run as
 my $user = $access{'user'};
 if ($user eq "*") {
 	$user = $remote_user;
 	}
 
 # Switch to given user
-if ($user eq "root") {
-	my $username = $in{'user'};
-	if ($username) {
-	my @uinfo = getpwnam($username);
-		if (@uinfo) {
-			$user = $username;
-			}
-		else {
-			&error(&text('index_euser', $username));
-			}
-		}
+if ($user eq "root" && $in{'user'}) {
+	defined(getpwnam($in{'user'})) ||
+		&error(&text('index_euser', &html_escape($in{'user'})));
+	$user = $in{'user'};
 	}
 
-defined(getpwnam($user)) || &error(&text('index_euser', $user));
+# Launch the shell server on the allocated port
+&foreign_require("cron");
+my $shellserver_cmd = "$module_config_directory/shellserver.pl";
+if (!-r $shellserver_cmd) {
+	&cron::create_wrapper($shellserver_cmd, $module_name, "shellserver.pl");
+	}
+defined(getpwnam($user)) || &error(&text('index_euser', &html_escape($user)));
 my $tmpdir = &tempname_dir();
 $ENV{'SESSION_ID'} = $main::session_id;
 &system_logged("$shellserver_cmd $port $user >$tmpdir/ws-$port.out 2>&1 </dev/null");
 
 # Open the terminal

Vulnerable code: # Launch the shell server on that port
&foreign_require("cron");
my $shellserver_cmd = "$module_config_directory/shellserver.pl";
if (!-r $shellserver_cmd) {
	&cron::create_wrapper($shellserver_cmd, $module_name, "shellserver.pl");
	}
if ($user eq "root") {
	my $username = $in{'user'};
	if ($username) {
	my @uinfo = getpwnam($username);
		if (@uinfo) {
			$user = $username;
			}
		else {
			&error(&text('index_euser', $username));
			}
		}
defined(getpwnam($user)) || &error(&text('index_euser', $user));
Fixed code: # Check permissions for user to run as
if ($user eq "root" && $in{'user'}) {
	defined(getpwnam($in{'user'})) ||
		&error(&text('index_euser', &html_escape($in{'user'})));
	$user = $in{'user'};
# Launch the shell server on the allocated port
&foreign_require("cron");
my $shellserver_cmd = "$module_config_directory/shellserver.pl";
if (!-r $shellserver_cmd) {
	&cron::create_wrapper($shellserver_cmd, $module_name, "shellserver.pl");
	}
defined(getpwnam($user)) || &error(&text('index_euser', &html_escape($user)));