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
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 */
 

Attachment: signature.asc
Description: Digital signature

Reply via email to