[Pkg-nagios-devel] Bug#416814: Cross-site scripting vulnerability

Christoph Biedl debian.packages.hhqj at manchmal.in-ulm.de
Tue Nov 6 10:20:03 UTC 2007


Florian Weimer wrote...

> The Nagios web front end does not HTML-escape status strings reported
> by monitored services.  As a result, these services can perform the
> usual cross-site scripting attacks, or worse. compromise the browser
> and gain access to the management network.

The patch attached
* backports the sanitazion prepared but not completed in 2.10.
* Works around the still empty "strip_plugin_html" in 2.10 by calling
  "html_encode".
* Fixes encoding of 8bit characters.
* Adds more space to "temp_expansion" in "html_encode", taken from CVS
  http://nagios.cvs.sourceforge.net/nagios/nagios/cgi/cgiutils.c?r1=1.44.2.5&r2=1.44.2.6

See my recent mail to nagios-devel for details.

Note that the patch against include/cgiutils.h.in will fail if the
recent patches due to #448371/CVE-2007-5624 have been applied. This can
be cured easily.

Status: Works for me

    Christoph
-------------- next part --------------
diff -urN nagios2-2.6.ORIG/cgi/avail.c nagios2-2.6/cgi/avail.c
--- nagios2-2.6.ORIG/cgi/avail.c	2006-04-06 00:33:32.000000000 +0200
+++ nagios2-2.6/cgi/avail.c	2007-11-06 11:16:56.000000000 +0100
@@ -3417,7 +3417,7 @@
 		printf("<td class='logEntries%s'>%s</td>",bgclass,end_date_time);
 		printf("<td class='logEntries%s'>%s</td>",bgclass,duration);
 		printf("<td class='logEntries%s'>%s%s</td>",ebgclass,entry_type,state_type);
-		printf("<td class='logEntries%s'>%s</td>",bgclass,(temp_as->state_info==NULL)?"":temp_as->state_info);
+		printf("<td class='logEntries%s'>%s</td>",bgclass,(temp_as->state_info==NULL)?"":html_encode(temp_as->state_info));
 		printf("</tr>\n");
 	        }
 
@@ -4038,7 +4038,7 @@
 
 		/* down times */
 		printf("<tr CLASS='dataOdd'><td CLASS='hostDOWN' rowspan=3>DOWN</td>");
-		printf("<td CLASS='dataOdd'>Unscheduled</td><td CLASS='dataOdd'>%s</td><td CLASS='dataOdd'>%2.3f%%</td><td class='dataOdd'>%2.3f%%</td></tr>\n",time_down_unscheduled_string,percent_time_down_unscheduled,percent_time_down_known);
+		printf("<td CLASS='dataOdd'>Unscheduled</td><td CLASS='dataOdd'>%s</td><td CLASS='dataOdd'>%2.3f%%</td><td class='dataOdd'>%2.3f%%</td></tr>\n",time_down_unscheduled_string,percent_time_down_unscheduled,percent_time_down_unscheduled_known);
 		printf("<tr CLASS='dataOdd'><td CLASS='dataOdd'>Scheduled</td><td CLASS='dataOdd'>%s</td><td CLASS='dataOdd'>%2.3f%%</td><td class='dataOdd'>%2.3f%%</td></tr>\n",time_down_scheduled_string,percent_time_down_scheduled,percent_time_down_scheduled_known);
 		printf("<tr CLASS='hostDOWN'><td CLASS='hostDOWN'>Total</td><td CLASS='hostDOWN'>%s</td><td CLASS='hostDOWN'>%2.3f%%</td><td class='hostDOWN'>%2.3f%%</td></tr>\n",time_down_string,percent_time_down,percent_time_down_known);
 
diff -urN nagios2-2.6.ORIG/cgi/cgiutils.c nagios2-2.6/cgi/cgiutils.c
--- nagios2-2.6.ORIG/cgi/cgiutils.c	2006-11-13 19:40:34.000000000 +0100
+++ nagios2-2.6/cgi/cgiutils.c	2007-11-06 11:18:08.000000000 +0100
@@ -1345,7 +1345,7 @@
 char * html_encode(char *input){
 	int len,output_len;
 	int x,y;
-	char temp_expansion[7];
+	char temp_expansion[10];
 
 	len=(int)strlen(input);
 	output_len=(int)sizeof(encoded_html_string);
@@ -1366,8 +1366,9 @@
 			y++;
 		        }
 
+#ifdef NOT_SO_SURE_ABOUT_THIS
 		/* spaces are encoded as non-breaking spaces */
-		else if((char)input[x]<=(char)' '){
+		else if((char)input[x]==(char)' '){
 
 			encoded_html_string[y]='\x0';
 			if((int)strlen(encoded_html_string)<(output_len-6)){
@@ -1375,11 +1376,30 @@
 				y+=6;
 			        }
 		        }
+#endif
+
+		else if((char)input[x]==(char)'<'){
+
+			encoded_html_string[y]='\x0';
+			if((int)strlen(encoded_html_string)<(output_len-4)){
+				strcat(encoded_html_string,"&lt;");
+				y+=4;
+			        }
+		        }
+
+		else if((char)input[x]==(char)'>'){
+
+			encoded_html_string[y]='\x0';
+			if((int)strlen(encoded_html_string)<(output_len-4)){
+				strcat(encoded_html_string,"&gt;");
+				y+=4;
+			        }
+		        }
 
 		/* for simplicity, everything else gets represented by its numeric value */
 		else{
 			encoded_html_string[y]='\x0';
-			sprintf(temp_expansion,"&#%d;",(unsigned int)input[x]);
+			sprintf(temp_expansion,"&#%d;",(unsigned char)input[x]);
 			if((int)strlen(encoded_html_string)<(output_len-strlen(temp_expansion))){
 				strcat(encoded_html_string,temp_expansion);
 				y+=strlen(temp_expansion);
@@ -1394,6 +1414,16 @@
 
 
 
+/* strips dangerous HTML from plugin output */
+char * strip_plugin_html(char *input){
+
+	/* TODO */
+	/* Use html_encode for the time being */
+	return html_encode(input);
+	}
+
+
+
 /* determines the log file we should use (from current time) */
 void get_log_archive_to_use(int archive,char *buffer,int buffer_length){
 	struct tm *t;
Binary files nagios2-2.6.ORIG/cgi/.cgiutils.c.swp and nagios2-2.6/cgi/.cgiutils.c.swp differ
diff -urN nagios2-2.6.ORIG/cgi/extinfo.c nagios2-2.6/cgi/extinfo.c
--- nagios2-2.6.ORIG/cgi/extinfo.c	2006-10-09 17:59:02.000000000 +0200
+++ nagios2-2.6/cgi/extinfo.c	2007-11-06 11:16:56.000000000 +0100
@@ -995,9 +995,9 @@
 
 		printf("<TR><TD CLASS='dataVar'>Host Status:</td><td CLASS='dataVal'><DIV CLASS='%s'>&nbsp;&nbsp;%s&nbsp;&nbsp;%s&nbsp;&nbsp;</DIV></td></tr>\n",bg_class,state_string,(temp_hoststatus->problem_has_been_acknowledged==TRUE)?"(Has been acknowledged)":"");
 
-		printf("<TR><TD CLASS='dataVar'>Status Information:</td><td CLASS='dataVal'>%s</td></tr>\n",(temp_hoststatus->plugin_output==NULL)?"":temp_hoststatus->plugin_output);
+		printf("<TR><TD CLASS='dataVar'>Status Information:</td><td CLASS='dataVal'>%s</td></tr>\n",(temp_hoststatus->plugin_output==NULL)?"":strip_plugin_html(temp_hoststatus->plugin_output));
 
-		printf("<TR><TD CLASS='dataVar'>Performance Data:</td><td CLASS='dataVal'>%s</td></tr>\n",(temp_hoststatus->perf_data==NULL)?"":temp_hoststatus->perf_data);
+		printf("<TR><TD CLASS='dataVar'>Performance Data:</td><td CLASS='dataVal'>%s</td></tr>\n",(temp_hoststatus->perf_data==NULL)?"":html_encode(temp_hoststatus->perf_data));
 
 		printf("<TR><TD CLASS='dataVar'>Current Attempt:</TD><TD CLASS='dataVal'>%d/%d</TD></TR>\n",temp_hoststatus->current_attempt,temp_hoststatus->max_attempts);
 
@@ -1305,9 +1305,9 @@
 			}
 		printf("<TR><TD CLASS='dataVar'>Current Status:</TD><TD CLASS='dataVal'><DIV CLASS='%s'>&nbsp;&nbsp;%s&nbsp;&nbsp;%s&nbsp;&nbsp;</DIV></TD></TR>\n",bg_class,state_string,(temp_svcstatus->problem_has_been_acknowledged==TRUE)?"(Has been acknowledged)":"");
 
-		printf("<TR><TD CLASS='dataVar'>Status Information:</TD><TD CLASS='dataVal'>%s</TD></TR>\n",(temp_svcstatus->plugin_output==NULL)?"":temp_svcstatus->plugin_output);
+		printf("<TR><TD CLASS='dataVar'>Status Information:</TD><TD CLASS='dataVal'>%s</TD></TR>\n",(temp_svcstatus->plugin_output==NULL)?"":strip_plugin_html(temp_svcstatus->plugin_output));
 
-		printf("<TR><TD CLASS='dataVar'>Performance Data:</td><td CLASS='dataVal'>%s</td></tr>\n",(temp_svcstatus->perf_data==NULL)?"":temp_svcstatus->perf_data);
+		printf("<TR><TD CLASS='dataVar'>Performance Data:</td><td CLASS='dataVal'>%s</td></tr>\n",(temp_svcstatus->perf_data==NULL)?"":html_encode(temp_svcstatus->perf_data));
 
 		printf("<TR><TD CLASS='dataVar'>Current Attempt:</TD><TD CLASS='dataVal'>%d/%d</TD></TR>\n",temp_svcstatus->current_attempt,temp_svcstatus->max_attempts);
 
diff -urN nagios2-2.6.ORIG/cgi/history.c nagios2-2.6/cgi/history.c
--- nagios2-2.6.ORIG/cgi/history.c	2006-03-21 22:31:46.000000000 +0100
+++ nagios2-2.6/cgi/history.c	2007-11-06 11:16:56.000000000 +0100
@@ -901,7 +901,7 @@
 
 				if(display_frills==TRUE)
 					printf("<img align='left' src='%s%s' alt='%s' title='%s'>",url_images_path,image,image_alt,image_alt);
-				printf("[%s] %s<br clear='all'>\n",date_time,temp_buffer);
+				printf("[%s] %s<br clear='all'>\n",date_time,strip_plugin_html(temp_buffer));
 				found_line=TRUE;
 			        }
 		        }
diff -urN nagios2-2.6.ORIG/cgi/notifications.c nagios2-2.6/cgi/notifications.c
--- nagios2-2.6.ORIG/cgi/notifications.c	2006-10-09 17:59:02.000000000 +0200
+++ nagios2-2.6/cgi/notifications.c	2007-11-06 11:16:56.000000000 +0100
@@ -714,7 +714,7 @@
 				printf("<td CLASS='notifications%s'>%s</td>\n",(odd)?"Even":"Odd",date_time);
 				printf("<td CLASS='notifications%s'><a href='%s?type=contacts#%s'>%s</a></td>\n",(odd)?"Even":"Odd",CONFIG_CGI,url_encode(contact_name),contact_name);
 				printf("<td CLASS='notifications%s'><a href='%s?type=commands#%s'>%s</a></td>\n",(odd)?"Even":"Odd",CONFIG_CGI,url_encode(method_name),method_name);
-				printf("<td CLASS='notifications%s'>%s</td>\n",(odd)?"Even":"Odd",temp_buffer);
+				printf("<td CLASS='notifications%s'>%s</td>\n",(odd)?"Even":"Odd",strip_plugin_html(temp_buffer));
 				printf("</tr>\n");
 			        }
 		        }
diff -urN nagios2-2.6.ORIG/cgi/showlog.c nagios2-2.6/cgi/showlog.c
--- nagios2-2.6.ORIG/cgi/showlog.c	2006-03-21 22:31:46.000000000 +0100
+++ nagios2-2.6/cgi/showlog.c	2007-11-06 11:16:56.000000000 +0100
@@ -513,7 +513,7 @@
 			
 			if(display_frills==TRUE)
 				printf("<img align='left' src='%s%s' alt='%s' title='%s'>",url_images_path,image,image_alt,image_alt);
-			printf("[%s] %s<br clear='all'>\n",date_time,(temp_buffer==NULL)?"":temp_buffer);
+			printf("[%s] %s<br clear='all'>\n",date_time,(temp_buffer==NULL)?"":strip_plugin_html(temp_buffer));
 		        }
 
 		printf("</DIV></P>\n");
diff -urN nagios2-2.6.ORIG/cgi/status.c nagios2-2.6/cgi/status.c
--- nagios2-2.6.ORIG/cgi/status.c	2006-10-09 17:59:02.000000000 +0200
+++ nagios2-2.6/cgi/status.c	2007-11-06 11:16:56.000000000 +0100
@@ -1729,7 +1729,7 @@
 			printf("<TD CLASS='status%s' nowrap>%s</TD>\n",status_bg_class,date_time);
 			printf("<TD CLASS='status%s' nowrap>%s</TD>\n",status_bg_class,state_duration);
 			printf("<TD CLASS='status%s'>%d/%d</TD>\n",status_bg_class,temp_status->current_attempt,temp_status->max_attempts);
-			printf("<TD CLASS='status%s'>%s&nbsp;</TD>\n",status_bg_class,(temp_status->plugin_output==NULL)?"":temp_status->plugin_output);
+			printf("<TD CLASS='status%s'>%s&nbsp;</TD>\n",status_bg_class,(temp_status->plugin_output==NULL)?"":strip_plugin_html(temp_status->plugin_output));
 
 			printf("</TR>\n");
 
@@ -2113,7 +2113,7 @@
 			printf("<TD CLASS='status%s'>%s</TD>\n",status_class,status);
 			printf("<TD CLASS='status%s' nowrap>%s</TD>\n",status_bg_class,date_time);
 			printf("<TD CLASS='status%s' nowrap>%s</TD>\n",status_bg_class,state_duration);
-			printf("<TD CLASS='status%s'>%s&nbsp;</TD>\n",status_bg_class,(temp_status->plugin_output==NULL)?"":temp_status->plugin_output);
+			printf("<TD CLASS='status%s'>%s&nbsp;</TD>\n",status_bg_class,(temp_status->plugin_output==NULL)?"":strip_plugin_html(temp_status->plugin_output));
 
 			printf("</TR>\n");
 		        }
diff -urN nagios2-2.6.ORIG/include/cgiutils.h.in nagios2-2.6/include/cgiutils.h.in
--- nagios2-2.6.ORIG/include/cgiutils.h.in	2006-01-20 18:34:53.000000000 +0100
+++ nagios2-2.6/include/cgiutils.h.in	2007-11-06 11:16:56.000000000 +0100
@@ -470,6 +470,7 @@
 
 char * url_encode(char *);		        		/* encodes a string in proper URL format */
 char * html_encode(char *);					/* encodes a string in HTML format (for what the user sees) */
+char * strip_plugin_html(char *);                               /* strips dangerous HTML from plugin output */
 
 void get_time_breakdown(unsigned long,int *,int *,int *,int *);	/* given total seconds, get days, hours, minutes, seconds */
 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://lists.alioth.debian.org/pipermail/pkg-nagios-devel/attachments/20071106/6981c325/attachment.pgp 


More information about the Pkg-nagios-devel mailing list