Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Security and Help with script 1

Status
Not open for further replies.

Rythemton

Technical User
May 10, 2002
78
US
I've created a script that allows people to send messages to members of a team or band. To send a message is accessed by calling
membermailer.cgi?member_name

The script looks through a data file for the member's name, and send the message to that member if their name is in the database. If their name is not in the database, it sends the message to a designated email to be printed and given as a hard copy to the member. The data file has each on it's own line in the form of
member_name,email@host.com

I've tried to make the script as secure as possible, but I'm new enough to CGI that I don't know all the security holes, so I'd like someone to look over the script and tell me of any seen.

Also, I'd like to make so that the member_name portion is case insensitive, but have been unsuccessful. Any ideas?

In testing the script has worked well. Some of the older versions of mailx don't support the ~R, but I haven't worried too much about that because most machines have sendmail, but I created the script to accept mailx because that is all that is available on the server this was created for.


The code:

#!/usr/bin/perl


# ---- USER DEFINED AREA ----


# email to send to when member has no email address
$master_email = "rythem\@iname.com";

# address book
$email_file = "/memberemail.txt";
$document_root = "/home/users/public";
$full_path = $document_root . $email_file;

# Set this to 1 if using sendmail, 0 for mailx or mail
$exists_sendmail = 0;

# Mail Program Path
$emailer = "/usr/bin/mailx";

# Cascading Style Sheet (leave empty for no style sheet)
$css_file = "Lords.css";

# Document Title
$page_title = "Dream Team Mailer";

# Link to another page (leave text empty for no link)
$link_text = "Return to the Dream Team";
$link_file = "team.html";


# ---- END OF USER EDITABLE ----


if ($ENV{'REQUEST_METHOD'} eq "GET") {
$going_to = $ENV{'QUERY_STRING'};
print <<End_Of_Head;
Content-type: text/html

<html>
<head>
<title>$page_title</title>
End_Of_Head
if ($css_file ne &quot;&quot;) {
print &quot;<link rel=\&quot;stylesheet\&quot; type=\&quot;text/css\&quot; href=\&quot;$css_file\&quot;></link>&quot;;
}
print <<End_Of_Form;
</head>
<body>
<h1>$page_title</h1>
Welcome to our member mailer. Fill in the form below to send your message
to $going_to. Please read the privacy warning below before submitting.
<p>
<FORM ACTION=&quot;membermailer.cgi&quot; METHOD=&quot;POST&quot;>
<table>
<tr><td>To:</td><td>$going_to</td></tr>
<tr><td>From:</td><td><INPUT TYPE=&quot;text&quot; NAME=&quot;name&quot; SIZE=40></td></tr>
<tr><td>Email Address:</td><td><INPUT TYPE=&quot;text&quot; NAME=&quot;from&quot; SIZE=40></td></tr>
<tr><td>Subject:</td><td><INPUT TYPE=&quot;text&quot; NAME=&quot;subject&quot; SIZE=40></td></tr>
</table>
Enter the message you have for our member:<br>
<TEXTAREA ROWS=6 COLS=60 NAME=&quot;message&quot;></TEXTAREA><br>
<INPUT TYPE=&quot;hidden&quot; NAME=&quot;sendto&quot; VALUE=&quot;$going_to&quot;>
<INPUT TYPE=&quot;submit&quot; VALUE=&quot;Send Message&quot;>
<INPUT TYPE=&quot;reset&quot; VALUE=&quot;Clear Form&quot;>
</FORM>
<p><a href=&quot;$link_file&quot;>$link_text</a>
<p><b>Privacy Warning:</b> Some members may not have an email address in our
database. The members without addresses will have their messages sent to another
member designated to deliver your message.
<p><font size='1'>&copy;Bullet Web Design Plus, All Rights Reserved 2002</font>
</body>
</html>
End_Of_Form
} elsif ($ENV{'REQUEST_METHOD'} eq &quot;POST&quot;) {
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(&quot;C&quot;, hex($1))/eg;
if (!$exists_sendmail){
$value =~ tr/\n\~/\n\~\~/;
}
$FORM{$name} = $value;
}
if ( open(READFILE,$full_path) ){
flock(READFILE,2);
while (<READFILE>) {
($name, $value) = split(/,/, $_);
$EMAILS{$name} = $value;
}
flock(READFILE,8);
close(READFILE);
} else {
&error_out(500,&quot;Unable to open data file&quot;);
}
if ( exists $EMAILS{$FORM{'sendto'}} ) {
$email_out = $EMAILS{$FORM{'sendto'}};
} else {
$email_out = $master_email;
}
if ($exists_sendmail){
if (open(MAILPROG,&quot;| $emailer -t&quot;)){
print MAILPROG <<mail_head;
To: $email_out
Reply-To: $FORM{'from'}
Subject: Mail for $FORM{'sendto'}; $FORM{'subject'}
mail_head
} else {
&error_out(500,&quot;Unable to open sendmail&quot;);
}
} else {
if (open(MAILPROG,&quot;| $emailer -s 'mailer' $email_out&quot;)){
print MAILPROG <<mail2_head;
~s Mail for $FORM{'sendto'}; $FORM{'subject'}
~R $FORM{'from'}
mail2_head
} else {
&error_out(500,&quot;Unable to open mailx&quot;);
}
}
print MAILPROG <<mail_body;
------------------------------------------------------
To: $FORM{'sendto'}
From: $FORM{'name'} <$FORM{'from'}>
Subject: $FORM{'subject'}
------------------------------------------------------
Message: $FORM{'message'}
------------------------------------------------------
Sent using $page_title
mail_body
close(MAILPROG);
print <<End_Of_Head2;
Content-type: text/html

<html>
<head>
<title>$page_title</title>
End_Of_Head2
if ($css_file ne &quot;&quot;) {
print &quot;<link rel=\&quot;stylesheet\&quot; type=\&quot;text/css\&quot; href=\&quot;$css_file\&quot;></link>&quot;;
}
print <<End_Of_Form2;
</head>
<body>
<h1>$page_title</h1>
Thank you for using our team mailer. The following has been sent to $FORM{'sendto'}.
<p>
Name: $FORM{'name'}<br>
email: $FORM{'from'}<br>
subject: $FORM{'subject'}<br>
Message: $FORM{'message'}
<p>
<p><a href=&quot;$link_file&quot;>$link_text</a>
<p><font size='1'>&copy;Bullet Web Design Plus, All Rights Reserved 2002</font>
</body>
</html>
End_Of_Form2
} else {
&error_out(500,&quot;Invalid Request Method&quot;)
}
exit(0);
sub error_out
{

local ($status, $keyword) = @_;
print &quot;Content-type: text/html&quot;, &quot;\n&quot;;
print &quot;Status: &quot;, $status, &quot; &quot;, $keyword, &quot;\n\n&quot;;
print <<End_of_Error;
<HTML>
<HEAD>
<TITLE>CGI Program - Unexpected Error</TITLE>
</HEAD>
<BODY>
<H1>$keyword</H1>
<HR>
Please contact the webmaster for more information.<br>
</BODY>
</HTML>
End_of_Error
exit(1);
}
 
In general, greatly oversimplified, as long as you stay inside your perl program, you are safe. The most common security holes occur when you ask the system to do something for you..... like opening a pipe to start a second process.


if (open(MAILPROG,&quot;| $emailer -s 'mailer' $email_out&quot;)){
print MAILPROG <<mail2_head;


That chunk is dangerous. The $email_out variable could contain stuff that, when passed to the system through the |, could do damage. You can imagine that if someone submitted some content that ended up in $email_out, when you open your pipe, that content is treated like a command.

Instead of pursuing this further, let me direct to Lincoln Stein's FAQ on the subject. This is very important reading for anyone doing CGI.



'hope this helps

If you are new to Tek-Tips, please use descriptive titles, check the FAQs, and beware the evil typo.
 
Thank you for looking it over. I know it's a long post, so I gave you a star.

The one line you mentioned, I did know about, and the $email_out is created by the script, not by any user. It's one of the dangers of using mailx, but sometimes you unfortunately have no other choice.

Thanks again,
Steve
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top