To put it politely, there are numerous difficulties with this code, not the least of which are many security holes. I'm not trying to be rude, but if you write CGI scripts, you need to know this.
- You are not untainting your incoming data. Get into the habit of doing this whenever you write CGI scripts.
- Your passwords are being read from a file where they are obviously not encrypted. If someone gains access to your system, they can read everyone's username/password combination.
- Your script gives out too much information, such as "Your password is incorrect". Don't give clues to potential hackers. Let 'em know that they succeeded or failed, that's it.
- I suspect that this script is not run on a secure server. If so, passwords are being sent in plain-text over the 'net and people can sniff them.
- You should modify the script to log bad password attempts or to send you an e-mail. Don't do the latter unless you have someone knowledgeable in security look it over; E-mail has its own dangers.
- Try to figure out a different authentication method. If you're using Apache, read up about .htaccess files.
Here's a somewhat cleaner version of your code. I haven't included the password encryption or the bad password logging, but the untainting and giving out of too much information is dealt with.
#!/usr/bin/perl -Tw
use strict; # Never, ever, write code without this
use CGI;
my $query = new CGI;
use vars qw($userid $pword);
my $password_dir = '/home/networkrichmond/dat/';
my $pword_file = ".passwrdlst";
my $passwrd_location = $password_dir . $pword_file;
my $userid_entd = $query->param('UserID');
my $pword_entd = $query->param('PWord');
# untaint incoming data
$userid_entd =~ /^([a-zA-Z0-9]*)$/; # This assumes only letters and nu
+mbers in userid
$userid_entd = $1; # Now it's untainted
$pword_entd =~ /^([a-zA-Z0-9]*)$/;
$pword_entd = $1;
if (-e $passwrd_location) {
# Note that we are using $! to get the actual error.
open USERFILE, $passwrd_location or die ("Could not open $pword_fi
+le: $!\n");
FINDUSER: {
while (<USERFILE>) {
chomp;
if (/^$userid_entd\|/o) {
($userid, $pword) = split /\|/;
last FINDUSER;
}
}
}
close(USERFILE);
}
print $query->header;
print $query->start_html;
if (($pword eq $pword_entd) && ($userid eq $userid_entd)) {
print "Authorization successful.\n";
} else {
print "Authorization unsuccessful.\n"
}
print $query->end_html;
It also looks like you stripped out some of the code as the %formdata hash is nowhere to be found. I suspect that you are parsing out the values by hand in a portion of the script that you haven't published, so I would recommend that you use Lincoln Stein's CGI module. CGI has many pitfalls and trying to do it by hand will bite you sooner or later. Incidentally, CGI.pm is now part of the standard Perl distribution, so you probably have it on your system.
The code above is only a quick hack and is still very unsecure. I won't explain all of the changes as they are too numerous to go into in detail. However, I recommend reading perlsec to begin learning about some of these issues.
Final note: you are using the hash %formdata to store your form values. This is the same hash name that Elizabeth Castro uses to store her form values. If you are using her "Perl and CGI" book, don't. The pages of that book and your fireplace should be intimately familiar with one another. For more information, read Perl and CGI for the World Wide Web.
Cheers,
Ovid | [reply] [d/l] |
if ($NotFound=="false") {
You should compare strings using eq, not ==. As it stands, this expression is always true.
--
<http://www.dave.org.uk>
European Perl Conference - Sept 22/24 2000, ICA, London
<http://www.yapc.org/Europe/> | [reply] [d/l] |
Have you considered providing authentication through /etc/apache/httpd.conf or /etc/apache/access.conf? I like it a bit better than .htaccess because it places all info in one place, instead of having .htaccess files throughout the directory structure. Works with /usr/bin/htpasswd just like .htaccess.
<Directory /var/www/private_html>
<Files foo.bar>
AuthName "Foo for Thought"
AuthType Basic
AuthUserFile /not/web/published/foo.htpasswd
Require valid-user
</Files>
</Directory>
cheers,
ybiC | [reply] [d/l] |
Le Oops... Thought I was logged in, try it again:
Have you considered providing authentication through /etc/apache/httpd.conf or /etc/apache/access.conf? I like it a bit better than .htaccess because it places all info in one place, instead of having .htaccess files throughout the directory structure. Works with /usr/bin/htpasswd just like .htaccess.
<Directory /var/www/private_html>
<Files foo.bar>
AuthName "Foo for Thought"
AuthType Basic
AuthUserFile /not/web/published/foo.htpasswd
Require valid-user
</Files>
</Directory>
cheers,
ybiC | [reply] [d/l] |
I always like htaccess :)
/****************************/
jason@gost.net, wh@ckz.org
http://jason.gost.net
/*****************************/
| [reply] [d/l] |