Re: Vetting a CGI script
by hardburn (Abbot) on Nov 12, 2003 at 17:37 UTC
|
It should reset $ENV{PATH} (which taint mode will force you to do anyway).
You will need to escape any pipe characters in the data from the client before it is printed to the file.
I suggest always using the three-element form of open that was made available in perl 5.6.0, though in this case it's not a big deal.
If you happen to be printing any user input in the e-mail headers, be sure to be very strict about what is allowed into them. About a month ago, we caught a spammer using one of our CGIs. The trick used was to put a new line in the to field followed by To: anyaddress@example.com, which was interpolated into the e-mail header. This would have allowed any address to be spammed, but the CGI appended our own domain name to the to field before sending, so all that happend was a lot of bounces. This made our e-mail admin very grumpy until we ran more strict validation on the fields, but it could have been worse. There were other fields that the spammer could have used that were also placed directly into the headers that didn't have anything appended to them. We are fortunate that the spammer wasn't quite that smart.
---- I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
-- Schemer
: () { :|:& };:
Note: All code is untested, unless otherwise stated
| [reply] [d/l] [select] |
|
In this case all the email header data is hard-coded in the script. Can anything bad be done with external data that is piped to sendmail for the body (after the "\n\n" that follows the header)?
------------------------------------------------------------
"Perl is a mess
and that's good because the
problem space is also a mess." - Larry Wall
| [reply] |
Re: Vetting a CGI script
by idsfa (Vicar) on Nov 12, 2003 at 18:02 UTC
|
For arbitrary input, consider that you are offering to set up a spam relay:
$in{myName} = "\n.\nMAIL FROM fake@dev.null\n"
. "RCPT TO poor@target.domain\n"
. "DATA\n$spam_message_goes_here\n\.\n"
. "MAIL FROM junk@throwaway\nRCPT TO nobody@nowhere\n"
. "DATA\n\nJust junk to avoid throwing an error"
... or anything else someone might want to do with access to your SMTP server. (Moral of story: Net::SMTP ... but I assume you are doing this as justification for a rewrite anyway.)
My parents just came back from a planet where the dominant life form had no
bilateral symmetry, and all I got was this stupid F-Shirt.
| [reply] [d/l] |
|
| [reply] |
|
$message = "From: blah\nTo: blah\nSubject: blah\n\nmessage\n";
open (SENDMAIL,"|sendmail -i);
print SENDMAIL $message;
close(SENDMAIL);
Updated:
(Yes, I know it could be done with multiple print's, but I hate dribbling information through a pipe ...)
Which is a bigger rewrite than moving to Net::SMTP:
use Net::SMTP;
$smtp = Net::SMTP->new('mailhost');
$smtp->mail($ENV{USER}); # print MAIL "MAIL FROM ..."
$smtp->to('postmaster'); # print MAIL "RCPT TO ..."
$smtp->data(); # print MAIL "DATA\n";
$smtp->datasend("line 1\n"); # print MAIL ...
$smtp->datasend("line 2\n"); # print MAIL ...
$smtp->datasend("line 3\n"); # print MAIL ...
$smtp->dataend();
$smtp->quit;
Updated: (duh ... typing "first" w/o a "second")
Second, invoking a whole 'nother app (sendmail) when you've already got perl running is just a bunch more overhead on your server. You then also have any security holes in 'sendmail -i' to remember to look for.
My parents just came back from a planet where the dominant life form had no
bilateral symmetry, and all I got was this stupid F-Shirt.
| [reply] [d/l] [select] |
|
|
| [reply] |
Re: Vetting a CGI script
by calin (Deacon) on Nov 12, 2003 at 17:35 UTC
|
I don't know anything about cgi-lib.pl. However, if I were to
code this fascist-style, these thoughts would cross my mind:
-
Use the three-or-more-argument version of open. It's safer.
-
Turn $mailprog into a lexically scoped variable or constant
(use constant ...). Messing with it is unlikely, but I'm following my fascist mindset.
-
Passing improperly untainted data to sendmail screams SPAM GATEWAY!
| [reply] [d/l] [select] |
Re: Vetting a CGI script
by hmerrill (Friar) on Nov 12, 2003 at 17:12 UTC
|
I've been using Perl for the last 6+ years, and I don't even remember cgi-lib.pl :)
I don't see a problem printing possibly tainted data to a file, but it really depends on what that file will be used for. I suppose you could say that untainting that data would be the responsibility of the program that *reads* that file. But my inclination would be to untaint the data before writing it to the file. I don't have much experience with -T taint mode, but I believe that if you intend to add the -T flag, that you'll have to untaint all external data (like form data) coming in first before using it anyway - so it's kind of a mute point.
As far as piping tainted data to sendmail, I thought I had read something somewhere about the flags to sendmail having something to do with security precautions, but I can't seem to find that. Read the perldocs on "How do I send mail?" by doing
perldoc -q mail
at a command prompt and search (using the forward slash "/") for "sendmail" - you'll find it. There are some slight sendmail flag differences between your code and what they suggest - I'm not sure if those differences are significant.
HTH. | [reply] [d/l] |
Re: Vetting a CGI script
by Zed_Lopez (Chaplain) on Nov 12, 2003 at 18:08 UTC
|
Security is really hard to impose after the fact. Ditch it, start over, use FormMail from the nms script archive.
| [reply] |
Re: Vetting a CGI script
by dvergin (Monsignor) on Nov 12, 2003 at 20:17 UTC
|
In addition to the helpful responses posted here, I appreciate Limbic~Region's reminder in the ChatterBox that we can't rely on the HTML form to impose length and content restrictions. It is easy to download a local copy of the page and modify it (or even to manually construct a posting URL).
In particular, Limbic~Region mentions the possibility of potential modification of the $CGI::DISABLE_UPLOADS and $CGI::POST_MAX values.
For me, this possibility places a greater burden on the receiving script. A)Nothing dangerous (like a malevolent cgi script) should be uploaded to a place where it could be invoked from the web and B)Massive return values from the form fields should probably be simply discarded rather than attempting to process/forward/store them.
In the current case, as best I can tell, uploads are not an issue. I assume someone could construct and post a response containing a dangerous or large upload. But without intervention by the receiving script, I presume it would simply languish in a tmp directory. A large, ininvited upload might slow the server down a bit or threaten the harddisk capacity, but there are other places (e.g. httpd.conf) to deal with that.
On the other hand, over-large form data needs to be anticipated and handled appropriately within the receiving script.
------------------------------------------------------------
"Perl is a mess
and that's good because the
problem space is also a mess." - Larry Wall
| [reply] |
|
| [reply] |
|
Great story. I'm bookmarking that.
And consider this: even if you don't have a million records to protect, you have computer resources to protect. If someone breaks into your machine, they can use it as a staging platform against someone else (or a warez site), diverting the blame (at least temporarily) toward you.
| [reply] |
|
Ok, I see how they were able to take over the machine in that example, but assuming you *have* to offer file upload, how can you protect against that? It's been a long time since I've worked with CGI's that offer file upload capability, and I think when we did, we handled it with CGI.pm. I don't recall specifying a "temp" directory. Is the solution to the problem you presented fixed by specifying a temp directory that is *NOT* the cgi-bin directory?
I just read some in 'perldoc CGI' - there's a section titled "-private_tempfiles" that describes security issues with file uploads and the snifibility of info being written to those temp files.
I guess I'm wondering what the *right* way to program file uploads - is using CGI.pm to do that a good way?
TIA.
| [reply] |
|
|
|