> RYAN, PAT OCT TUT LISTING FILE
> LC: 212
1. An HTML form, **order.html**, used by the fictitious Yoyodyne Corp.
to collect order information via Mosaic.
Yoyodyne Corp. Product Order Form
Product Order
2. The CGI program, **process_order**, called from within **order.html**.
#!/usr/bin/perl
#
eval "exec /usr/bin/perl -S $0 $*" if $running_under_some_shell;
# extra include directories
push(@INC,'/app/people/guide/GUIDE/server/WWW/httpd_1.1/cgi-bin');
require 'ctime.pl';
require 'cgi-lib.pl';
chop($now = &ctime(time()));
# Read in everything from httpd.
&ReadParse;
# Send the initial info back to the server.
print &PrintHeader;
print "Results of Your Order Submission\n";
unless ($in{'name'}) {
print "You must include your name in any order.";
exit 0;
}
if ($in{'cc'} && !$in{'email'}) {
print <<_EOT_;
You asked for a carbon copy of your order but did not include your
email address. Please add your address and resubmit your order.
_EOT_
exit 0;
}
# Open up temporary file for ordering system
$order_file = "/tmp/order.$$";
open(ORDER,">$order_file");
print ORDER <<_EOT_;
NAME: $in{'name'}
ADDRESS:
$in{'address'}
PHONE: $in{'phone'}
EMAIL: $in{'email'}
PAYMENT: $in{'payment'}
ACCOUNT: $in{'account'}
AUTHORIZATION: $in{'key'}
_EOT_
print ORDER "ITEMS:\n";
$n=0;
foreach(split(/\n/,$in{'items'}))
{ ++$n; printf ORDER "%3d\t%s\n",$n,$_; }
print ORDER "RECEIVED: $now\n";
print ORDER "\n";
print ORDER <<_EOT_;
REMOTE: $ENV{'REMOTE_HOST'}
_EOT_
print ORDER "\n";
close ORDER;
# Send the order to the Processing database
$cmd = "/usr/local/bin/process_order $order_file";
system $cmd;
# If requested, send the user a copy of the order.
if ($in{'cc'} && $in{'email'})
{
@addresses=($in{'email'});
$to = join(' ',@addresses);
# Escape any suspicious characters
$to=&protect($to);
$mail_cmd = "/bin/mail";
$cmd = "$mail_cmd $to";
unless (open(MAIL,"| $cmd")) {
print <<_EOT_;
An error occurred while trying to submit your order. Please contact
root@yoyodyne.com.
_EOT_
exit 0;
}
print MAIL "\n";
open(ORDER,"<$order_file");
while ()
{ print MAIL $_; }
print MAIL "\n";
close MAIL;
close ORDER;
}
print <<_EOT_;
Thank you. Your order was received at $now and has been sent to
the Processing Department.
_EOT_
unlink($order_file);
exit 0;
sub protect
# Quotify characters which are special to the shell
{
local($_)=@_;
s!([;:&\$'`|()])!\\$1!g; # Use backslash to escape metacharactors
$_;
}
3. Test script **cgi_test**
#!/usr/bin/perl
#
# CGI script to process Software Modification Requests (SMRs)
# ryan@odouls.stx.com (patrick m. ryan)
#
eval "exec /usr/bin/perl -S $0 $*" if $running_under_some_shell;
# extra include directories
push(@INC,'/app/people/guide/GUIDE/server/WWW/httpd_1.1/cgi-bin');
push(@INC,'/app/people/ryan/perl');
require 'cgi-lib.pl';
require 'date.pl';
$now = &date(time()-(4*3600));
select STDOUT;
$|=1;
# Suck in everything from httpd.
&ReadParse;
print &PrintHeader;
print "
CGI test\n";
print &PrintVariables(%in);
print &PrintVariables(%ENV);
exit 0;
Table 1: Routines available in the **cgi-lib.pl** Perl library, and
useful in writing CGI scripts.
[*] ReadParse
Read and parse the input from the server. After this routine
has been run, several global variables will exist:
**$in** a scalar that contains the entire input line.
**@in** an array of strings of the form __name=value__.
**%in** an associative array where
**$in{**__name__**}=**__value__.
[*] PrintHeader
Returns a line meant to be the first line sent back to standard
output.
[*] PrintVariables
Collects all of the form values and formats them into an HTML
unordered list suitable for sending to standard output. This
routine is useful for testing.
[Listing 4. This didn't appear in the printed version--had to be cut
for space reasons. rf]
You have an HTML form that returns a variable called **address** that
should contain a user's email address. In your Perl CGI script, you have
copied this value to a variable called **$address**. You want to mail some
information to this address so you put the following code in your Perl CGI
program:
# Send confirmation back to the user.
open(MAIL, "|/bin/mail $address");
print MAIL
"Your order has been sent to the Processing Department. Your PO number is $number\n";
close MAIL;
A normal user would send a value like **joe@verylarge.com**. The second
parameter to Perl's **open()** function would be sent a value of
"|/bin/mail joe@verylarge.com". No problem.
The unscrupulous cracker, however, might use a bogus address and then
follow it with a semicolon and another command. This cracker could type
"/dev/null; rm -rf /home". Unless the CGI program notices the semicolon
embedded in the **$address** address, the **open()** command would be sent
"|/bin/mail /dev/null; rm -rf /home". **/bin/mail** would cheerfully send
a message to **/dev/null**. The system would then treat the text after the
semicolon as another command and merrily proceed to destroy the **/home**
filesystem.
[end listing 4]
-30-