One of my custom monitors was printing the output of a syslog entry
as its summary output. The syslog entry was from a mail program,
so it had stuff like "to=<[EMAIL PROTECTED]>". But in mon.cgi's
output in my Web browser, it just said "to=".
This is because mon.cgi is just dropping the output into a web page,
where the browser parses it for HTML. Years ago we added a call
to HTML::Entities:encode_entities to mon.cgi so that messages typed
in with the ACK command would not get confused with HTML - the attached
patch extends that functionality to monitor output.
There are security implications here - if an outside party could get
control of the output of a Mon script (easy in my case, since the data
comes from syslog and includes error messages from a remote host), that
outside party could cobble together some HTML that eventually gets
executed in the Mon user's browser (i.e. cross-site scripting).
The attached patch renames the "untaint_ack_msgs" parameter to
"untaint_all_msgs" and, when set, not only untaints ACK messages,
but also untaints last_summary and last_detail output before displaying
it.
I recommend that we remove this parameter completely and always untaint
messages before displaying them in the CGI interface - it's the right
thing to do. The cost is one more Perl module dependency, but there
are already a host of Perl modules needed to run mon and one more is
not going to hurt much.
I haven't worked on this code for several years so I may have missed
something - an extra pair of eyes on this patch would be appreciated.
-- Ed
--- mon.cgi.pl 2005-04-21 16:56:29.000000000 -0400
+++ mon2.cgi.pl 2007-07-12 10:32:59.000000000 -0400
@@ -143,7 +143,7 @@
$monhost_and_port_args $monhost_and_port_args_meta
$has_read_config $moncgi_config_file $cf_file_mtime
$mon11
- $untaint_ack_msgs @show_watch @no_watch $show_watch_strict
+ $untaint_all_msgs @show_watch @no_watch $show_watch_strict
$required_mon_client_version);
# Formatting-related global vars
use vars qw($BGCOLOR $TEXTCOLOR $LINKCOLOR $VLINKCOLOR
@@ -224,7 +224,7 @@
$cookie_name = "mon-cookie"; #name of cookie given to browser
for auth
$cookie_path = "/"; # path for auth cookie
# Set this to "" for auto-path set
- $untaint_ack_msgs = "yes"; # Use HTML::Entities to scrub
user-supplied ack messages (recommended!)
+ $untaint_all_msgs = "yes"; # Use HTML::Entities to scrub
user-supplied ack messages (recommended!)
# Define optional regexes in the @show_watch variable,
# and only hostgroups which match one of these regexes
# will be shown.
@@ -367,10 +367,10 @@
#
# Used to escape HTML in ack's
#
-if ($untaint_ack_msgs =~ /^y(es)?$/i) {
+if ($untaint_all_msgs =~ /^y(es)?$/i) {
eval "use HTML::Entities" ;
} else {
- undef $untaint_ack_msgs;
+ undef $untaint_all_msgs;
}
@@ -1104,7 +1104,7 @@
# user requested it, otherwise, just pass it on through
# as is.
if ( $op{$group}{$service}{'ack'} != 0 ) {
- if ($untaint_ack_msgs) {
+ if ($untaint_all_msgs) {
#
# We untaint
#
@@ -1186,7 +1186,8 @@
$webpage->print("<td align=left bgcolor=\"$td_bg_color\">");
$webpage->print("$service_disabled_string<a
href=\"$url?${monhost_and_port_args}command=svc_details&args=$group,$service\">");
$webpage->print("<font
size=+1><b>${service}</b></font></a>${desc_string} : \n");
- $webpage->print("<font size=+1>$s->{last_summary}</font>\n");
+ $webpage->print("<font size=+1>" .
+ $untaint_all_msgs ?
HTML::Entities::encode_entities($s->{last_summary}) : $s->{last_summary} .
"</font>\n");
$webpage->print("<br>($failure_string)");
$webpage->print(" ${service_acked_string}") if
$service_acked_string ne "";
$webpage->print("</td>\n");
@@ -1642,9 +1643,18 @@
$webpage->print("</td></tr>");
# Now print the detail and summary information for the failed service
- $op{$group}->{$service}->{'last_summary'} = "<not specified>" if
$op{$group}->{$service}->{'last_summary'} eq "" ;
- $op{$group}->{$service}->{'last_detail'} = "<not specified>" if
$op{$group}->{$service}->{'last_detail'} eq "" ;
- $op{$group}->{$service}->{'last_detail'} =~ s/\n/<BR>/g;
+ if ($op{$group}->{$service}->{'last_summary'} eq "") {
+ $op{$group}->{$service}->{'last_summary'} = "<not
specified>";
+ } elsif ($untaint_all_msgs) {
+ $op{$group}->{$service}->{'last_summary'} =
HTML::Entities::encode_entities($op{$group}{$service}{'last_summary'})
+ }
+ if ($op{$group}->{$service}->{'last_detail'} eq "" ) {
+ $op{$group}->{$service}->{'last_detail'} = "<not
specified>"
+ } elsif ($untaint_all_msgs) {
+ $op{$group}->{$service}->{'last_detail'} =
HTML::Entities::encode_entities($op{$group}{$service}{'last_detail'})
+ } else { # not much of an untaint
+ $op{$group}->{$service}->{'last_detail'} =~ s/\n/<BR>/g;
+ };
$webpage->print("<tr><td width=25%><font size=+1
color=\"$font_color\">Failure
summary</font>:</td><td>$op{$group}->{$service}->{'last_summary'}</td></tr>\n");
$webpage->print("<tr><td width=25%><font size=+1
color=\"$font_color\">Failure
detail</font>:</td><td>$op{$group}->{$service}->{'last_detail'}</td></tr>\n");
$webpage->print("</table>");
@@ -3651,8 +3661,8 @@
return 0;
}
$dtlog_max_failures_per_page = $val;
- } elsif ($key eq "untaint_ack_msgs") {
- $untaint_ack_msgs = $val;
+ } elsif ($key eq "untaint_all_msgs") {
+ $untaint_all_msgs = $val;
} elsif ($key eq "watch") {
push(@show_watch, $val);
} elsif ($key eq "show_watch_strict") {
_______________________________________________
mon mailing list
[email protected]
http://linux.kernel.org/mailman/listinfo/mon