CVE-2017-9313: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Multiple Cross-site scripting (XSS) vulnerabilities in Webmin before 1.850 allow remote attackers to inject arbitrary web script or HTML via the sec parameter to view_man.cgi, the referers parameter to change_referers.cgi, or the name parameter to save_user.cgi. NOTE: these issues were not fixed in 1.840.
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: 2017-07-04T02:29Z
Repository: https://github.com/webmin/webmin
Language: Other
Files changed: acl/save_user.cgi, software/file_info.cgi, software/search.cgi, webmin/change_referers.cgi
Commit date: 2017-06-12 14:12:39 -0700
Commit message: escape some params

Diff: diff --git a/acl/save_user.cgi b/acl/save_user.cgi
index 49f9e17162..6fecf776ea 100755
--- a/acl/save_user.cgi
+++ b/acl/save_user.cgi
@@ -50,15 +50,15 @@ else {
 	}
 &error_setup($text{'save_err'});
 
 # Validate username, and check for a clash
 $in{'name'} =~ /^[A-z0-9\-\_\.\@]+$/ && $in{'name'} !~ /^\@/ ||
-	&error(&text('save_ename', $in{'name'}));
+	&error(&text('save_ename', &html_escape($in{'name'})));
 $in{'name'} eq 'webmin' && &error($text{'save_enamewebmin'});
 if (!$in{'old'} || $in{'old'} ne $in{'name'}) {
 	my $clash = &get_user($in{'name'});
-	$clash && &error(&text('save_edup', $in{'name'}));
+	$clash && &error(&text('save_edup', &html_escape($in{'name'})));
 	}
 !$access{'logouttime'} || $in{'logouttime_def'} ||
 	$in{'logouttime'} =~ /^\d+$/ || &error($text{'save_elogouttime'});
 !$access{'minsize'} || $in{'minsize_def'} ||
 	$in{'minsize'} =~ /^\d+$/ || &error($text{'save_eminsize'});
diff --git a/software/file_info.cgi b/software/file_info.cgi
index 13d0fb16de..4ba14aa922 100755
--- a/software/file_info.cgi
+++ b/software/file_info.cgi
@@ -18,11 +18,12 @@ else {
 	# absolute path.. must exist in DB
 	&installed_file($f);
 	}
 
 if (!%file) {
-	print "<b>",&text('file_notfound', "<tt>$f</tt>"),"</b><p>\n";
+	print "<b>",&text('file_notfound',
+			  "<tt>".&html_escape($f)."</tt>"),"</b><p>\n";
 	}
 else {
 	# display file info
 	$nc = "width=10% nowrap";
 	print &ui_table_start($text{'file_title'}, "width=100%", 4);
diff --git a/software/search.cgi b/software/search.cgi
index 862a3c0049..b267aa7048 100755
--- a/software/search.cgi
+++ b/software/search.cgi
@@ -32,11 +32,12 @@ if (@match == 1 && $in{'goto'}) {
 &ui_print_header(undef, $text{'search_title'}, "", "search");
 
 if (@match) {
 	@match = sort { lc($packages{$a,'name'}) cmp lc($packages{$b,'name'}) }
 		      @match;
-	print "<b>",&text('search_match', "<tt>$s</tt>"),"</b><p>\n";
+	print "<b>",&text('search_match',
+			  "<tt>".&html_escape($s)."</tt>"),"</b><p>\n";
 	print &ui_form_start("delete_packs.cgi", "post");
 	print &ui_hidden("search", $in{'search'});
 	@tds = ( "width=5" );
 	@links = ( &select_all_link("del", 0),
 		   &select_invert_link("del", 0) );
diff --git a/webmin/change_referers.cgi b/webmin/change_referers.cgi
index ed7130cfb9..34a3b3c2af 100755
--- a/webmin/change_referers.cgi
+++ b/webmin/change_referers.cgi
@@ -8,11 +8,12 @@ require './webmin-lib.pl';
 
 &lock_file("$config_directory/config");
 $gconfig{'referer'} = $in{'referer'};
 @refs = split(/\s+/, $in{'referers'});
 foreach my $r (@refs) {
-	$r =~ /^[a-z0-9\.\-\_]+$/ || &error(&text('referers_ehost', $r));
+	$r =~ /^[a-z0-9\.\-\_]+$/ ||
+		&error(&text('referers_ehost', &html_escape($r)));
 	}
 $gconfig{'referers'} = join(" ", @refs);
 $gconfig{'referers_none'} = int(!$in{'referers_none'});
 &write_file("$config_directory/config", \%gconfig);
 &unlock_file("$config_directory/config");

Vulnerable code: 	&error(&text('save_ename', $in{'name'}));
	$clash && &error(&text('save_edup', $in{'name'}));
	print "<b>",&text('file_notfound', "<tt>$f</tt>"),"</b><p>\n";
	print "<b>",&text('search_match', "<tt>$s</tt>"),"</b><p>\n";
	$r =~ /^[a-z0-9\.\-\_]+$/ || &error(&text('referers_ehost', $r));
Fixed code: 	&error(&text('save_ename', &html_escape($in{'name'})));
	$clash && &error(&text('save_edup', &html_escape($in{'name'})));
	print "<b>",&text('file_notfound',
			  "<tt>".&html_escape($f)."</tt>"),"</b><p>\n";
	print "<b>",&text('search_match',
			  "<tt>".&html_escape($s)."</tt>"),"</b><p>\n";
	$r =~ /^[a-z0-9\.\-\_]+$/ ||
		&error(&text('referers_ehost', &html_escape($r)));