Discussion:
Writing or copying file to another directory
(too old to reply)
Paul E. Schoen
2010-08-25 21:25:43 UTC
Permalink
I have a simple form mailing script that I've added to. I can get the
results formatted in HTML sent to stdout to appear on the new web page in
the IE8 browser, and I can write the same to a file in the cgi-bin
directory, which is "output.htm" and chdir 777. But I want to write the file
in the directory where the HTML for the submit form is located, and nothing
seems to work. Here is the script with things I tried. I have searched the
docs and FAQs and online but nothing seems to work for a different
directory, which also has the files with 777 permissions.

The HTML with JavaScript is live at
http://www.smart.net/~pstech/SCGBG/EventSubmitJS.htm It checks the Full Name
entry as a simple password. The correct name as coded below will actually
send an email to me.

Any help will be appreciated. Thanks!

Paul

----------------------------------------------------------------------

#!/usr/bin/perl
#
# mailer.pl-- A simple program to mail form data to an email address
#
# Written in 1997 by James Marshall, ***@jmarshall.com
# For the latest, see http://www.jmarshall.com/easy/cgi/
#

# IMPORTANT: MAKE SURE THESE TWO VALUES ARE SET CORRECTLY FOR YOU!
# This is the location in smart.net
$mailprog= "/usr/bin/sendmail" ;

$recipient= "paul\@peschoen.com" ; # make sure to \ escape the @

# Get the CGI input variables
%in= &getcgivars ;

if($in{'Full_Name'} ne 'Paul E. Schoen') {
&HTMLdie("Unauthorized user: $in{'Full_Name'}");}

# Open the mailing process
open(MAIL, "|$mailprog $recipient")
|| &HTMLdie("Couldn't send the mail (couldn't run $mailprog).") ;

# Print the header information
$ENV{'HTTP_REFERER'} || ($ENV{'HTTP_REFERER'}= "www.peschoen.com") ;
print MAIL "From: $in{'Email'}\n",
"Subject: Form data from $in{'Full_Name'}\n\n",
"The following data was entered at $ENV{'HTTP_REFERER'}:\n\n" ;

# Find length of longest field name, for formatting; include space for colon
$maxlength= 0 ;
foreach (keys %in) {
$maxlength= length if length > $maxlength ;
}
$maxlength++ ;

# Print each CGI variable received by the script, one per line.
# This just prints the fields in alphabetical order. To define your own
# order, use something like
# foreach ('firstname', 'lastname', 'phone', 'address1', ... ) {
foreach ('Full_Name', 'Email', 'Event_Title','Event_Date','Event_Time',
'Event_Description') {

# If a field has newlines, it's probably a block of text; indent it.
if ($in{$_}=~ /\n/) {
$in{$_}= "\n" . $in{$_} ;
$in{$_}=~ s/\n/\n /g ;
$in{$_}.= "\n" ;
}

# comma-separate multiple selections
$in{$_}=~ s/\0/, /g ;

# Print fields, aligning columns neatly
printf MAIL "%-${maxlength}s %s\n", "$_:", $in{$_} ;
}


# Close the process and mail the data

close(MAIL) ;

# Print an HTML response to the user
$eTitle=$in{'Event_Title'};
$eDate=$in{'Event_Date'};
$eTime=$in{'Event_Time'};
$eDescr=$in{'Event_Description'};
print <<EOF ;
Content-type: text/html

<html>
<body>
<h3>Your data has been sent.</h3>
<p><h3>$eTitle</h3>
<h4>Date: $eDate</h4>
<h4>Time: $eTime</h4>
$eDescr</p>
</body>
</html>
EOF

########## Here's where the problems are; the rest seems to work OK
#################

# Print to the HTML file (write, append, create)
#chdir('/home/pstech/www/SCGBG/'); #still writes to cgi-bin
#open DATA1, '>', "/home/pstech/www/SCGBG/output.txt" or HTMLdie ("File
error: $!"); #No such file/dir
#open DATA1, '>', "output.txt" or HTMLdie ("File error: $!"); #Writes to
cgi-bin OK
open DATA1, '>', "output.htm" or HTMLdie ("File error: $!"); #Writes to
cgi-bin OK
#open my DATA1, '>', "output.htm" or HTMLdie ("File error: $!"); #Internal
server error
#open DATA1, '>', "//home//pstech//www//SCGBG//output.txt" or HTMLdie ("File
error: $!"); #No such file/dir
#copy("output.htm","/home/pstech/www/SCGBG/output.htm") or HTMLdie ("File
error: $!"); #doesn't work, no error
#copy("output.htm","/www/SCGBG/output.htm") or HTMLdie ("File error: $!");
#doesn't work, no error
open DATA1, '>', "output.htm" or HTMLdie ("File error: $!"); #Writes to
cgi-bin OK

print DATA1 <<EOF ;
Content-type: text/html

<html>
<body>
<p><h3>$eTitle</h3>
<h4>Date: $eDate</h4>
<h4>Time: $eTime</h4>
$eDescr</p>
</body>
</html>
EOF

close (DATA1);
#use File::copy; #Internal server error
#copy("output.htm","test.htm") or HTMLdie ("File error: $!"); #doesn't work,
no error msg, clears source file?
#copy("output.htm","../SCGBG/output.htm") or HTMLdie ("File error: $!");
#doesn't work, no error msg
copy("output.htm","output.txt") or HTMLdie ("File error: $!"); #doesn't
work, no error msg

exit ;

...(Subroutines)
Ben Morrow
2010-08-25 22:01:23 UTC
Permalink
Post by Paul E. Schoen
I have a simple form mailing script that I've added to. I can get the
results formatted in HTML sent to stdout to appear on the new web page in
the IE8 browser, and I can write the same to a file in the cgi-bin
directory, which is "output.htm" and chdir 777. But I want to write the file
in the directory where the HTML for the submit form is located, and nothing
seems to work. Here is the script with things I tried. I have searched the
docs and FAQs and online but nothing seems to work for a different
directory, which also has the files with 777 permissions.
The HTML with JavaScript is live at
http://www.smart.net/~pstech/SCGBG/EventSubmitJS.htm It checks the Full Name
entry as a simple password. The correct name as coded below will actually
send an email to me.
Any help will be appreciated. Thanks!
Paul
----------------------------------------------------------------------
#!/usr/bin/perl
#
# mailer.pl-- A simple program to mail form data to an email address
#
# For the latest, see http://www.jmarshall.com/easy/cgi/
#
Where is

use warnings;
use strict;

? Have you read the Posting Guidelines? (The fact you didn't write this
doesn't excuse you.)
Post by Paul E. Schoen
# IMPORTANT: MAKE SURE THESE TWO VALUES ARE SET CORRECTLY FOR YOU!
# This is the location in smart.net
$mailprog= "/usr/bin/sendmail" ;
# Get the CGI input variables
%in= &getcgivars ;
Don't call subs with '&'.
Post by Paul E. Schoen
if($in{'Full_Name'} ne 'Paul E. Schoen') {
&HTMLdie("Unauthorized user: $in{'Full_Name'}");}
# Open the mailing process
open(MAIL, "|$mailprog $recipient")
|| &HTMLdie("Couldn't send the mail (couldn't run $mailprog).") ;
Use multi-arg open.
Use lexical filehandles.

open(my $MAIL, "|-", $mailprog, $recipient)
|| HTMLdie("...");

<snip>
Post by Paul E. Schoen
# Close the process and mail the data
close(MAIL) ;
You are writing to MAIL, so you need to check the return value of close.

<snip>
Post by Paul E. Schoen
# Print to the HTML file (write, append, create)
#chdir('/home/pstech/www/SCGBG/'); #still writes to cgi-bin
Does this directory exist? Can the CGI process see it? Is the CGI
process running chrooted?
Post by Paul E. Schoen
#open DATA1, '>', "/home/pstech/www/SCGBG/output.txt" or HTMLdie ("File
error: $!"); #No such file/dir
...apparently not.
Post by Paul E. Schoen
#open DATA1, '>', "output.txt" or HTMLdie ("File error: $!"); #Writes to
cgi-bin OK
open DATA1, '>', "output.htm" or HTMLdie ("File error: $!"); #Writes to
cgi-bin OK
#open my DATA1, '>', "output.htm" or HTMLdie ("File error: $!"); #Internal
server error
That's not the right syntax. Perl would at least have told you something
was wrong (the actual error message is less than helpful,
unfortunately).
Post by Paul E. Schoen
#open DATA1, '>', "//home//pstech//www//SCGBG//output.txt" or HTMLdie ("File
error: $!"); #No such file/dir
Don't just make things up without some understanding of what you are
doing.
Post by Paul E. Schoen
#copy("output.htm","/home/pstech/www/SCGBG/output.htm") or HTMLdie ("File
error: $!"); #doesn't work, no error
#copy("output.htm","/www/SCGBG/output.htm") or HTMLdie ("File error: $!");
#doesn't work, no error
Where do you expect copy() to come from? It's not a builtin.
Post by Paul E. Schoen
close (DATA1);
See above.
Post by Paul E. Schoen
#use File::copy; #Internal server error
Case matters. It's File::Copy.
Post by Paul E. Schoen
#copy("output.htm","test.htm") or HTMLdie ("File error: $!"); #doesn't work,
no error msg, clears source file?
Unlikely. More likely it was never created in the first place, because
the script failed before it got that far.

Ben
Sherm Pendley
2010-08-25 22:29:34 UTC
Permalink
Post by Ben Morrow
? Have you read the Posting Guidelines? (The fact you didn't write this
doesn't excuse you.)
More to the point, the fact that you didn't write this script doesn't
make its many problems any less problematic. It needs a *lot* of work,
so unless you want to dive in and become a Perl developer yourself,
my best advice to you is to find a better one.

NMS formmail has a good reputation:

<http://nms-cgi.sourceforge.net/>

I think I recall you mentioning DreamHost in another group - they have
a built-in formmail script you can use:

<http://wiki.dreamhost.com/Formmail>

sherm--
--
Sherm Pendley
<camelbones.sourceforge.net>
Cocoa Developer
Paul E. Schoen
2010-08-26 06:44:37 UTC
Permalink
Post by Ben Morrow
Where is
use warnings;
use strict;
It works with warnings, but strict causes it to fail
Post by Ben Morrow
? Have you read the Posting Guidelines? (The fact you didn't write this
doesn't excuse you.)
Yes, I have read the guidelines, and I think I followed them to the best of
my ability as a newbie.
Post by Ben Morrow
Post by Paul E. Schoen
# Get the CGI input variables
%in= &getcgivars ;
Don't call subs with '&'.
It did not work when I removed the &
Post by Ben Morrow
Post by Paul E. Schoen
open(MAIL, "|$mailprog $recipient")
|| &HTMLdie("Couldn't send the mail (couldn't run $mailprog).") ;
Use multi-arg open.
Use lexical filehandles.
open(my $MAIL, "|-", $mailprog, $recipient)
|| HTMLdie("...");
It does not work with "my".
Post by Ben Morrow
Post by Paul E. Schoen
close(MAIL) ;
You are writing to MAIL, so you need to check the return value of close.
Yes, that is good practice. I will need to check the details of the
function. Boolean?
Post by Ben Morrow
Post by Paul E. Schoen
#chdir('/home/pstech/www/SCGBG/'); #still writes to cgi-bin
Does this directory exist? Can the CGI process see it? Is the CGI
process running chrooted?
The directory exists and I can go there using Telnet "cd
/home/pstech/www/SCGBG/". I don't know what "chrooted" means.
Post by Ben Morrow
Post by Paul E. Schoen
#open DATA1, '>', "/home/pstech/www/SCGBG/output.txt" or HTMLdie ("File
error: $!"); #No such file/dir
...apparently not.
It works in Telnet if I use "pico /home/pstech/www/SCGBG/output.txt"
Post by Ben Morrow
Case matters. It's File::Copy.
use File::Copy; #was Internal server error - Changed case - PES
$file1="output.htm";
$file2="output.txt"; #this works, copies in same directory
copy($file1, $file2) or HTMLdie ("File error: $file2 $!");
$file2="/home/pstech/www/SCGBG/output.htm"; #this fails, no such file or dir
copy($file1, $file2) or HTMLdie ("File error: $file2 $!");

I made the following changes to a test script, ran it directly using Telnet,
corrected the errors, and now it compiles and works:

--------------------------------------------------------------------------

#!/usr/bin/perl
#
# TestCopy.pl
# Written in 2010 by Paul E. Schoen

use warnings;
use strict;

use File::Copy; #was Internal server error - Changed case - PES
my $file1="output.htm";
my $file2="output.txt"; #this works, copies in same directory
copy($file1, $file2) or HTMLdie ("File error: $file2 $!");
$file2="/home/pstech/www/SCGBG/output.htm"; #this works, copies in other dir
copy($file1, $file2) or HTMLdie ("File error: $file2 $!");

exit ;

# Die, outputting HTML error page
# If no $title, use a default title
sub HTMLdie {
my($msg, $title)= @_ ;
$title= "CGI Error" if $title eq '' ;
print <<EOF ;
Content-type: text/html

<html>
<head>
<title>$title</title>
</head>
<body>
<h1>$title</h1>
<h3>$msg</h3>
</body>
</html>
EOF

exit ;
}

-----------------------------------------------------------

Thanks for your help. I need to learn more about how to debug a script. The
error messages were very helpful. But I'm not sure if I can run the mailer
script from Telnet. Is there a way to see the compiler error messages,
perhaps in an error log?

Paul
Paul E. Schoen
2010-08-26 07:49:28 UTC
Permalink
I found that, after making corrections to the mailer.js script so it would
compile from the Telnet command line, it would perform the file copy to the
other directory where the HTML file is located, outside of cgi-bin. But when
I run it, or the TestCopy.pl, from the browser, it gives the CGI error:

File error: /home/pstech/www/SCGBG/output.htm No such file or directory

That is a confusing message, as the file does exist in that directory. I
think it must be something to do with the server configuration. I do need to
use a different URL:

http://www.smart.net/pstech-cgi-bin/TestCopy.pl

to run the script. If I use the normal URL:

http://www.smart.net/~pstech/cgi-bin/TestCopy.pl

I just get the text of the TestCopy.pl script.

Paul
Tad McClellan
2010-08-26 19:03:59 UTC
Permalink
Post by Paul E. Schoen
http://www.smart.net/~pstech/cgi-bin/TestCopy.pl
I just get the text of the TestCopy.pl script.
This is very very bad.

Bad People can do Bad Things even without seeing the code that is
being run.

Giving them access to the code, makes it even easier for them to crack
your site.

If you don't want to suffer an attack, you should contact your
provider and figure out how to get them to stop doing that.
--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.liamg\100cm.j.dat/"
The above message is a Usenet post.
I don't recall having given anyone permission to use it on a Web site.
Ben Morrow
2010-08-26 20:10:35 UTC
Permalink
Post by Tad McClellan
This is very very bad.
Bad People can do Bad Things even without seeing the code that is
being run.
Giving them access to the code, makes it even easier for them to crack
your site.
I think the Open Source movement might have an issue with this
assertion...

Ben
Randal L. Schwartz
2010-08-26 20:31:50 UTC
Permalink
Ben> I think the Open Source movement might have an issue with this
Ben> assertion...

Nope. The Open Source movement says the same thing. If bad guys can
see the source, they can break it easier.

The Open Source movement offsets this with, "but if the good guys can
also see it, and FIX it, then the risk is appropriately mitigated."

print "Just another Perl hacker,"; # the original
--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<***@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion
Paul E. Schoen
2010-08-29 04:05:25 UTC
Permalink
Post by Randal L. Schwartz
Ben> I think the Open Source movement might have an issue with this
Ben> assertion...
Nope. The Open Source movement says the same thing. If bad guys can
see the source, they can break it easier.
The Open Source movement offsets this with, "but if the good guys can
also see it, and FIX it, then the risk is appropriately mitigated."
print "Just another Perl hacker,"; # the original
Just to let you know I have fixed the perl script so that it no longer shows
errors using strict and warnings. I am concerned about security especially
now that I have FTP access to the Sierra Club server. For now I just have
links to the web page on my server, as "under construction", and that page
links to the CGI mailer.pl script also on my server which emails the
information to me and also converts it to HTML and copies it to a file.

I have the permissions on these files as 777 but I probably want to remove
the write and possibly the read permissions in the cgi-bin folder. Does an
executable script, accessed by anyone through a link in the web page, have
write permission to files with permission set at, for example, 700? And
should the mailer.pl script have permission 711 to keep anyone other than
myself from reading or writing it?

My problems were mostly because of the host configuration, and the sys admin
told me that it was set up as a "jail" which restricted access. I do believe
it is running SUEXEC. Hopefully now I will not need to deal with those
issues and I will need to balance my efforts between the HTML with
JavaScript on one hand, with the CGI perl script on the other. Since I may
not have the time and enthusiasm to become proficient in perl I may try to
do as much processing as possible in the JavaScript of the HTML document,
although it may be better suited to server side scripting.

Thanks for all your help and patience. I was amused "joey's" thread on the
simple loop.

Paul
www.pstech-inc.com
Ben Morrow
2010-08-29 04:33:00 UTC
Permalink
Post by Paul E. Schoen
I have the permissions on these files as 777 but I probably want to remove
the write and possibly the read permissions in the cgi-bin folder. Does an
executable script, accessed by anyone through a link in the web page, have
write permission to files with permission set at, for example, 700? And
should the mailer.pl script have permission 711 to keep anyone other than
myself from reading or writing it?
You can't make a perl script unreadable. The perl interpreter needs to
be able to read the file in order to run the script.
Post by Paul E. Schoen
My problems were mostly because of the host configuration, and the sys admin
told me that it was set up as a "jail" which restricted access.
Jails are a form of chroot, so this may be the cause of your file access
problems.

Ben
Paul E. Schoen
2010-08-29 18:53:15 UTC
Permalink
Post by Ben Morrow
Post by Paul E. Schoen
I have the permissions on these files as 777 but I probably want to remove
the write and possibly the read permissions in the cgi-bin folder. Does an
executable script, accessed by anyone through a link in the web page, have
write permission to files with permission set at, for example, 700? And
should the mailer.pl script have permission 711 to keep anyone other than
myself from reading or writing it?
You can't make a perl script unreadable. The perl interpreter needs to
be able to read the file in order to run the script.
I have added an index.html file to the cgi-bin directory which just displays
"Restricted access" and does not allow public viw of the directory, which at
least gives a bit better security. But I don't fully understand how the UNIX
system determines the identity of the originator of a read, write, or
execute request. If I log on using Telnet or an FTP program, it seems a bit
clearer, but when I use a browser to access a web page which calls a CGI
script, is my identity used to determine the file permissions I have? Is the
perl interpreter assumed to be a public entity? And then when my perl script
reads or writes to a file in the cgi-bin or another directory, are the
permissions based on my original identity as determined by the browser?

I'd like to have things set up with the maximum possible level of security,
but still allow the necessary processes to take place. I found this document
about security: http://www.w3.org/Security/Faq/wwwsf1.html and it answered
some questions. The perl faq was not helpful except to say that the perl
source is not easily hidden.
Post by Ben Morrow
Post by Paul E. Schoen
My problems were mostly because of the host configuration, and the sys admin
told me that it was set up as a "jail" which restricted access.
Jails are a form of chroot, so this may be the cause of your file access
problems.
Yes, I was given a special URL to access a file from the perl script, and
now the files are found and can be written. But could a public or anonymous
user also use that URL to write to the file? I suppose I'm not very worried
about someone using my scripts for their own purposes (especially if they
are not well-written), but I would not want to supply enough clues for a
malicious hacker to cause mayhem. I can probably get good information from
my Smartnet system administrator, but I think these issues are frequently
encountered when adding CGI and perl scripts to a website and it would
probably be worth including in the perl FAQ.

Thanks,

Paul
Jürgen Exner
2010-08-29 19:20:43 UTC
Permalink
Post by Paul E. Schoen
But I don't fully understand how the UNIX
system determines the identity of the originator of a read, write, or
execute request.
This really has pretty much nothing to do with Perl. It would be the
same if you used a different programming language or even a totally
different application.
Post by Paul E. Schoen
If I log on using Telnet or an FTP program, it seems a bit
clearer, but when I use a browser to access a web page which calls a CGI
script, is my identity used to determine the file permissions I have?
Please define "_my_ identity". Unless the program did a setuid or chown
it will run under whatever user called it. For CGI scripts that's often
'nobody' or 'www' or some other special account with very low
permissions.
Post by Paul E. Schoen
Is the perl interpreter assumed to be a public entity?
In general yes because there would be little point in having private
copies of it.
Post by Paul E. Schoen
And then when my perl script
reads or writes to a file in the cgi-bin or another directory, are the
permissions based on my original identity as determined by the browser?
Yes, typically they will be the same as the web browser's ID, e.g.
"nobody" or 'www' or whatever the sysadmin determined the cgi server
should run under.
Post by Paul E. Schoen
I'd like to have things set up with the maximum possible level of security,
but still allow the necessary processes to take place. I found this document
about security: http://www.w3.org/Security/Faq/wwwsf1.html and it answered
some questions. The perl faq was not helpful except to say that the perl
source is not easily hidden.
Well, that's not surprising considering that Perl doesn't require (or
offers) anything different compared to other programming languages.

You have a CGI question, not a Perl question. Why would a CGI question
be answered in a Perl FAQ?
Post by Paul E. Schoen
Yes, I was given a special URL to access a file from the perl script, and
now the files are found and can be written. But could a public or anonymous
user also use that URL to write to the file?
That depends how the web server has been set up. You need to ask in NG
that actually deals with the web server you are using.
Post by Paul E. Schoen
but I think these issues are frequently
encountered when adding CGI and perl scripts to a website and it would
probably be worth including in the perl FAQ.
They are just as frequently encountered when adding CGI and C or Fortran
or Cobol or Haskell or $name_your_favourite_programming_lang to a web
site. Therefore they should be answered in a CGI FAQ and not in the Perl
FAQ.

jue
Tad McClellan
2010-08-29 21:14:08 UTC
Permalink
Post by Jürgen Exner
Post by Paul E. Schoen
I'd like to have things set up with the maximum possible level of security,
but still allow the necessary processes to take place. I found this document
about security: http://www.w3.org/Security/Faq/wwwsf1.html and it answered
some questions. The perl faq was not helpful except to say that the perl
source is not easily hidden.
Well, that's not surprising considering that Perl doesn't require (or
offers) anything different compared to other programming languages.
Other programming languages have taint checking?
--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.liamg\100cm.j.dat/"
The above message is a Usenet post.
I don't recall having given anyone permission to use it on a Web site.
Jürgen Exner
2010-08-29 22:33:12 UTC
Permalink
Post by Tad McClellan
Post by Jürgen Exner
Post by Paul E. Schoen
I'd like to have things set up with the maximum possible level of security,
but still allow the necessary processes to take place. I found this document
about security: http://www.w3.org/Security/Faq/wwwsf1.html and it answered
some questions. The perl faq was not helpful except to say that the perl
source is not easily hidden.
Well, that's not surprising considering that Perl doesn't require (or
offers) anything different compared to other programming languages.
Other programming languages have taint checking?
Yes, you are right. There are a few Perl-specific features for
CGI-programming like the taint checking that you mentioned. Those most
certainly belong into a "CGI in Perl" FAQ / document / man-page /
tutorial / .... .

But access rights of the web server do not fall into that category.

jue
Paul E. Schoen
2010-08-30 15:14:57 UTC
Permalink
Post by Jürgen Exner
Post by Tad McClellan
Post by Jürgen Exner
Post by Paul E. Schoen
I'd like to have things set up with the maximum possible level of security,
but still allow the necessary processes to take place. I found this document
about security: http://www.w3.org/Security/Faq/wwwsf1.html and it answered
some questions. The perl faq was not helpful except to say that the perl
source is not easily hidden.
Well, that's not surprising considering that Perl doesn't require (or
offers) anything different compared to other programming languages.
Other programming languages have taint checking?
Yes, you are right. There are a few Perl-specific features for
CGI-programming like the taint checking that you mentioned. Those most
certainly belong into a "CGI in Perl" FAQ / document / man-page /
tutorial / .... .
But access rights of the web server do not fall into that category.
OK, I think I understand it more clearly now. I tried to find a newsgroup
specific to CGI but they appear to be inactive. I just thought it would be
helpful to add a topic in the FAQ about where to look for information on
server-side issues and security, since AFAIK perl is the predominate
language used for that purpose. I have requested that the administrator of
my account look at my website files on the server and let me know of any
security issues.

My next step in this project will be to add an activity to the list based on
the data that someone enters in the form provided for that purpose. It
should be sorted by date, and then converted to HTML for the home page to
display. It seems that a server-side script would be best for this purpose,
and Perl may be the best choice, but I might also look into using C or Java
because I am more familiar with the syntax. I might also be able to use
JavaScript in the HTML form submission document to convert to HTML, but I
would still need a server side script to write the file to the server.

I might do some searching for Perl scripts that already do most of what I
need. But I also need to make sure they are well written, which is nearly
impossible for me to determine since the language is still quite foreign to
me. If you can give me some advice as to where I can find what I need, then
I promise I won't bug you guys any more.

Thanks for all you have done so far.

Paul

Tad McClellan
2010-08-29 21:40:55 UTC
Permalink
Post by Paul E. Schoen
But I don't fully understand how the UNIX
system determines the identity of the originator of a read, write, or
execute request.
Every process is run by a "user", identified by a UID (User IDentifier,
a number) which corresponds to a name, often called a "login" or
"account" or "user".

Perl has a special varable named $< that contains the UID of the
owner of the process that the Perl program is running in.

It also has a function that can cross-reference from the UID to
the login name:

my $uid = $<;
my $login = getpwuid($<);
print "uid=$uid login=$login\n";

So, if you are wondering who your Perl program is running as, insert
code like the above and see for sure who it is running as.
Post by Paul E. Schoen
If I log on using Telnet or an FTP program, it seems a bit
clearer,
In that case, you are whatever user your provider setup for you,
such as "pschoen" or "pauls" or whatever.
Post by Paul E. Schoen
but when I use a browser to access a web page which calls a CGI
script,
A browser makes an "HTTP Request".

A web server services that request, and provides an "HTTP Response".

This is how the WWW works.

Browsers do not really access a web page, they issue an HTTP Request
and recieve an HTTP Response.

Web pages never call CGI programs.

The Web Server might call a CGI program in the course of fulfilling
a request though.

Understanding the fundamentals of how the WWW works is valuable...
Post by Paul E. Schoen
is my identity used to determine the file permissions I have?
... because it allows you to answer that question.

Your CGI program runs as the *web server* user, which is often "www"
or "nobody", but can be pretty much anything it depends on how your
provider has configured their web server.

(it is also possible that the CGI program runs as "pschoen" but that
too depends on how your web server is configured. Are you getting the
sense that none of this permission stuff is specific to Perl? I hope
so. You would have the same issues if you were using Python or C.
You really must know how the web server that you are using is
configured, contact your provider.
)
Post by Paul E. Schoen
Is the
perl interpreter assumed to be a public entity?
What does "public entity" mean when you say it?

perl never logs in. It's "identity" is the same as the process
that it is running in.
Post by Paul E. Schoen
And then when my perl script
reads or writes to a file in the cgi-bin or another directory, are the
permissions based on my original identity as determined by the browser?
Permissions are never determined by the browser.

Permissions are determined by the owner of the process that is
running the program (whether written in Perl or not). (that process
was, in turn, started by the web server.)

In a shell session, that is likely to be "pschoen" or somesuch.

In a CGI environment, that is like to be "www" or some such.
--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.liamg\100cm.j.dat/"
The above message is a Usenet post.
I don't recall having given anyone permission to use it on a Web site.
Ben Morrow
2010-08-26 08:52:52 UTC
Permalink
Post by Paul E. Schoen
Post by Ben Morrow
Where is
use warnings;
use strict;
It works with warnings, but strict causes it to fail
So fix the errors. That's the whole point of turning 'strict' on.
Post by Paul E. Schoen
Post by Ben Morrow
? Have you read the Posting Guidelines? (The fact you didn't write this
doesn't excuse you.)
Yes, I have read the guidelines, and I think I followed them to the best of
my ability as a newbie.
Post by Ben Morrow
Post by Paul E. Schoen
# Get the CGI input variables
%in= &getcgivars ;
Don't call subs with '&'.
It did not work when I removed the &
Read the docs on how to call subs. In this case you want

my %in = getcgivars();
Post by Paul E. Schoen
Post by Ben Morrow
Post by Paul E. Schoen
open(MAIL, "|$mailprog $recipient")
|| &HTMLdie("Couldn't send the mail (couldn't run $mailprog).") ;
Use multi-arg open.
Use lexical filehandles.
open(my $MAIL, "|-", $mailprog, $recipient)
|| HTMLdie("...");
It does not work with "my".
In what sense 'does not work'? You did notice the '$', right? That needs
to be added everywhere else you use the filehandle, too (the whole point
is to get a filehandle in a normal variable, rather than the
globally-scoped named filehandles you were using before).
Post by Paul E. Schoen
Post by Ben Morrow
Post by Paul E. Schoen
close(MAIL) ;
You are writing to MAIL, so you need to check the return value of close.
Yes, that is good practice. I will need to check the details of the
function. Boolean?
perldoc -f close
Post by Paul E. Schoen
Post by Ben Morrow
Post by Paul E. Schoen
#chdir('/home/pstech/www/SCGBG/'); #still writes to cgi-bin
Does this directory exist? Can the CGI process see it? Is the CGI
process running chrooted?
The directory exists and I can go there using Telnet "cd
/home/pstech/www/SCGBG/". I don't know what "chrooted" means.
man 2 chroot

Check the permissions on all the directories in that path. I suspect
that's more likely the problem than chroot.

You can see what user the CGI ends up running as by printing $>. You can
convert that number to a name with

use User::pwent;

print getpwuid($>)->name;
Post by Paul E. Schoen
Post by Ben Morrow
Case matters. It's File::Copy.
use File::Copy; #was Internal server error - Changed case - PES
$file1="output.htm";
$file2="output.txt"; #this works, copies in same directory
copy($file1, $file2) or HTMLdie ("File error: $file2 $!");
$file2="/home/pstech/www/SCGBG/output.htm"; #this fails, no such file or dir
copy($file1, $file2) or HTMLdie ("File error: $file2 $!");
This is failing the same as before. You need to find out why the CGI
process can't see the /home/pstech/www/SCGBG directory.

You could try something like

for (qw(
/ /home /home/pstech /home/pstech/www /home/pstech/www/SCGBG
)) {
print "$_: " . (-d $_) . "\n";
}

which might show you where the problem is.
Post by Paul E. Schoen
Thanks for your help. I need to learn more about how to debug a script. The
error messages were very helpful. But I'm not sure if I can run the mailer
script from Telnet. Is there a way to see the compiler error messages,
perhaps in an error log?
There ought to be. Talk to your provider if you don't know where you
should be looking. You can't possibly debug something if you can't see
the error message.

You can also use the CGI::Carp module to send errors and warnings to the
browser, but remember to turn it off before you put the script into
production (warning messages like that are valuable information for
attackers).

Ben
Mart van de Wege
2010-08-26 11:51:52 UTC
Permalink
Post by Paul E. Schoen
Post by Ben Morrow
Where is
use warnings;
use strict;
It works with warnings, but strict causes it to fail
This is a bad sign.

If the fix is trivial, fix it, but otherwise, if the script isn't built
to run under 'strict', it's a waste of time to try and rewrite it so it
does.[1]

Mart

[1] And before someone chimes in: yes, that's a rule of thumb, I'm sure
you can think of exceptions. That's not the point.
--
"We will need a longer wall when the revolution comes."
--- AJS, quoting an uncertain source.
Sherm Pendley
2010-08-26 13:14:25 UTC
Permalink
Post by Paul E. Schoen
Post by Ben Morrow
Where is
use warnings;
use strict;
It works with warnings, but strict causes it to fail
Strict doesn't "cause" failures, it simply shows you the failures that
would otherwise have been overlooked.

Like I said, this code is horrid. Kudos to you if you're looking to
learn Perl, but don't start with this script as a basis - you'll learn
some *awful* habits if you do.

sherm--
--
Sherm Pendley
<camelbones.sourceforge.net>
Cocoa Developer
Tad McClellan
2010-08-26 18:57:45 UTC
Permalink
Post by Paul E. Schoen
Post by Ben Morrow
Where is
use warnings;
use strict;
It works with warnings, but strict causes it to fail
Then modify the program so that strict does cause it to fail.

If you have questions about how to modify the program so that strict
does not cause it to fail, then post a question about modifying your
program so that strict will not cause it to fail.
Post by Paul E. Schoen
Post by Ben Morrow
Post by Paul E. Schoen
%in= &getcgivars ;
Don't call subs with '&'.
It did not work when I removed the &
Use parens on the end instead of ampersand at the front:

my %in = getcgivars();


(But you should throw that code you got from the Web into the trash
where it belongs, and use a proper module for accessing form values.
)

You can replace it easily, as suggested in one of the answers to the
FAQs quoted below.

use CGI 'Vars';
...
my %in = Vars();
Post by Paul E. Schoen
Post by Ben Morrow
Post by Paul E. Schoen
open(MAIL, "|$mailprog $recipient")
|| &HTMLdie("Couldn't send the mail (couldn't run $mailprog).") ;
Use multi-arg open.
Use lexical filehandles.
open(my $MAIL, "|-", $mailprog, $recipient)
|| HTMLdie("...");
It does not work with "my".
Beware of saying "doesn't work"
This is a "red flag" phrase. If you find yourself writing that,
pause and see if you can't describe what is not working without
saying "doesn't work". That is, describe how it is not what you
want.


What did you observe that led you to believe that it did not work?

We are generally not very good at mind reading...

Did it fail to run?

Did it run but made the wrong output?

Did it issue any messages?

Did it make smoke come out of your computer's vents?

Did it start a global thermonuclear war?
Post by Paul E. Schoen
Post by Ben Morrow
Post by Paul E. Schoen
close(MAIL) ;
You are writing to MAIL, so you need to check the return value of close.
Yes, that is good practice. I will need to check the details of the
function.
Good idea.
Post by Paul E. Schoen
Boolean?
Checking the details of the function should enable you to answer
that question without being dependent on others:

perldoc -f close
Post by Paul E. Schoen
Post by Ben Morrow
Post by Paul E. Schoen
#chdir('/home/pstech/www/SCGBG/'); #still writes to cgi-bin
Does this directory exist? Can the CGI process see it? Is the CGI
process running chrooted?
The directory exists and I can go there
But your CGI program is most likely not running as you, so what
you can do is not relevant.

What is relevant is what the user that your CGI program runs as
(often "nobody" or "www" or somesuch, it depends on how your web
server was setup) can do.
Post by Paul E. Schoen
using Telnet "cd
/home/pstech/www/SCGBG/". I don't know what "chrooted" means.
http://lmgtfy.com/?q=chroot
Post by Paul E. Schoen
I need to learn more about how to debug a script.
As with most things, you start with the Frequently Asked Questions:

perldoc -q debug

How do I debug my Perl programs?
Post by Paul E. Schoen
The
error messages were very helpful. But I'm not sure if I can run the mailer
script from Telnet.
It is not relevant whether or not you can run it.

What is relevant is what the user that your CGI program runs as
(often "nobody" or "www" or somesuch, it depends on how your web
server was setup) can do.
Post by Paul E. Schoen
Is there a way to see the compiler error messages,
perhaps in an error log?
As with most things, you start with the Frequently Asked Questions:

perldoc -q CGI

How can I make my CGI script more efficient?

Where can I learn about CGI or Web programming in Perl?

What is the correct form of response from a CGI script?

My CGI script runs from the command line but not the browser.
(500 Server Error)

===> How can I get better error messages from a CGI program?

How do I make sure users can't enter values into a form that
cause my CGI script to do bad things?

How do I decode a CGI form?
--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.liamg\100cm.j.dat/"
The above message is a Usenet post.
I don't recall having given anyone permission to use it on a Web site.
Steve
2010-08-26 17:34:57 UTC
Permalink
Post by Tad McClellan
Post by Paul E. Schoen
Post by Ben Morrow
Post by Paul E. Schoen
#chdir('/home/pstech/www/SCGBG/'); #still writes to cgi-bin
Does this directory exist? Can the CGI process see it? Is the CGI
process running chrooted?
The directory exists and I can go there
But your CGI program is most likely not running as you, so what
you can do is not relevant.
Ummm.... if it is NOT running scripts as the site owner/user, then the
web server is not running SUEXEC.

That in itself is a huge red flag, since anyone on the server can access
his scripts, and more importantly, any authentication values in the
scripts or in configuration files.

In other words, Paul's scripts have no security at all......

Personally, I would never even consider doing CGI on a shared server
that was not running SUEXEC.

my $.02

It's been a few years since I used it, but I believe the below might
tell Paul if the server is running SUEXEC:

#!/usr/bin/perl

use warnings;
use strict;

my $real_uid = $<;
my $uid_name = getpwuid($real_uid);

my $effective_uid = $>;
my $eff_name = getpwuid( $effective_uid );

my $real_group = $(;
my $group_name = getgrgid($real_group);

my $effective_group = $);
my $eff_group = getgrgid( $effective_group );


print "Content-type: text/plain\n\n";


print qq~
Real User: $real_uid / $uid_name
Process User: $effective_uid / $eff_name
Real Group: $real_group / $group_name
Process Group: $effective_group / $eff_group
~;

The output(s) should match... on my local box I get this:

Real User: 502 / testuser
Process User: 502 / testuser
Real Group: 416 416 / apache
Process Group: 416 416 / apache

If Real User and Process User do NOT match... well...


\s
Ben Morrow
2010-08-26 20:09:39 UTC
Permalink
Post by Steve
Ummm.... if it is NOT running scripts as the site owner/user, then the
web server is not running SUEXEC.
That in itself is a huge red flag, since anyone on the server can access
his scripts, and more importantly, any authentication values in the
scripts or in configuration files.
(To my mind CGI is in and of itself a security hole. I always use
FastCGI, now, with an independantly-stared FastCGI-process running as a
dedicated user...)
Post by Steve
In other words, Paul's scripts have no security at all......
Personally, I would never even consider doing CGI on a shared server
that was not running SUEXEC.
my $.02
It's been a few years since I used it, but I believe the below might
#!/usr/bin/perl
use warnings;
use strict;
my $real_uid = $<;
my $uid_name = getpwuid($real_uid);
my $effective_uid = $>;
my $eff_name = getpwuid( $effective_uid );
No. This will tell you if you are running setid; but suEXEC does a
'full' setid setting both real and effective IDs, so you won't see it.
(Incidentally, this means perl won't turn on taint mode for you. Make
sure to remember to do that yourself.)

You need to check if $> is your uid, or the webserver's.

Ben
Steve
2010-08-26 18:39:03 UTC
Permalink
Post by Ben Morrow
Post by Steve
Ummm.... if it is NOT running scripts as the site owner/user, then the
web server is not running SUEXEC.
That in itself is a huge red flag, since anyone on the server can access
his scripts, and more importantly, any authentication values in the
scripts or in configuration files.
(To my mind CGI is in and of itself a security hole. I always use
FastCGI, now, with an independantly-stared FastCGI-process running as a
dedicated user...)
Post by Steve
In other words, Paul's scripts have no security at all......
Personally, I would never even consider doing CGI on a shared server
that was not running SUEXEC.
my $.02
It's been a few years since I used it, but I believe the below might
#!/usr/bin/perl
use warnings;
use strict;
my $real_uid = $<;
my $uid_name = getpwuid($real_uid);
my $effective_uid = $>;
my $eff_name = getpwuid( $effective_uid );
No. This will tell you if you are running setid; but suEXEC does a
'full' setid setting both real and effective IDs, so you won't see it.
(Incidentally, this means perl won't turn on taint mode for you. Make
sure to remember to do that yourself.)
You need to check if $> is your uid, or the webserver's.
Ben
As I say, it's been a number of years since I used that code, but as I
recalled, on a non-SUEXEC Apache setup, it would return different user
names, and the same on SUEXEC.

A quick test shows that you are right and my memory was faulty. (surpirse)

At any rate it will tell you who the CGI is running as....

The *same* virtual host with SUEXEC

Real User: 502 / testuser
Process User: 502 / testuser
Real Group: 416 416 / apache
Process Group: 416 416 / apache

And then without SUEXEC:

Real User: 480 / apache
Process User: 480 / apache
Real Group: 416 416 / apache
Process Group: 416 416 / apache


So... I guess it would be more accurate to say that if the Real and
Process user is the owner of the script as opposed to Apache, then
SUEXEC is turned on/enabled.


thanks for looking over my shoulder Ben.

\s
Tad McClellan
2010-08-25 23:16:35 UTC
Permalink
$recipient= '***@peschoen.com'; # make sure to use the appropriate quotes...
--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.liamg\100cm.j.dat/"
The above message is a Usenet post.
I don't recall having given anyone permission to use it on a Web site.
Continue reading on narkive:
Loading...