|
Perl Case Study - Password CGI There are many reasons to restrict access to a script or web page. Of course there's no 100% secure way to do it, even with a Secure Socket Layer (https), but in most cases, a simple password routine in your CGI script will do. In theory, how does this work? A user would input a password into a field (for accounts you usually have to enter in a username and a password). Then the CGI script would take this password and compare it to a predefined value that is either stored in the script itself, or in a file. The process:
1.Get the the inputted password Modifications for use:
1.Encryption - sometimes you may want to implement a simple encryption; just
realize that this is easily crackable by experienced "hackers," however,
setting a directory unreadable to the browser will allow you to avoid password
stealing (although server side includes might still cause a security
problem).
Getting the InputWe can use our Form CGI case study material to handle the input (this kind of application seems to be very flexible for handling various script tasks). So we get our information through a form (or through the URL's GET method). Let's say that the input fields were named "username" and "password"; the data inputted would be stored in $FORM{'username'} and $FORM{'password'}. Authentification/ValidationLet's start with the simplest case: the correct username and password previously defined in the script itself.
#!/usr/local/bin/perl
$correctUsername = "adinfinitum"; print "Content-type:text/html\n\n";
#################
if ($ENV{'REQUEST_METHOD'} eq 'GET') { $buffer = $ENV{'QUERY_STRING'}; } @pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
################
#Use a nested if/else statement like the one below to make debugging else { print "Username Incorrect.\n"; }
See this script in action: password-simple-test.shtml Multiple User AuthentificationThe above is sufficient if you need only one set of username|password. Let's make it a tad more resourceful by getting the data from a file - and this time we should be able to maintain more than one set (perhaps to personalize). I've named this supplementary password list file passwd.txt. Check it out; you'll notice that I've entered three sets already. You can, of course, add as many as needed :) It may become resource intensive if there are over 5,000-10,000 entries, but otherwise, it works abundantly well. What you need to do:
1.Get the list from the file.
#!/usr/local/bin/perl print "Content-type:text/html\n\n";
#################
if ($ENV{'REQUEST_METHOD'} eq 'GET') { $buffer = $ENV{'QUERY_STRING'}; } @pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
################
open(LIST, "passwd.txt");
foreach $line(@pass) { Notice that this "upgrade" has only a few extra lines of modifications. You basically have the idea of how this works if you've followed along so far; it the comparison that makes the difference. Now how about some of those extra features? EncryptionWe have the option to encrypt a username and/or password using the crypt function. It will return the value of the encrypted word or phrase, using the following syntax in the script: $encryptedPassword = crypt($password,$salt); What is $salt, you ask? It is simply a "seed" value, consisting of 2 characters (i.e. 2 alphanumeric values), that is used in creating the encryption. You could simply have $salt be something you define in the script, but that's a bit unsafe since your encrypted password would always start with those same two letters. See for yourself experimenting with our simple encryption testing device. [You can also use this to manually encrypt passwords for use in this example :)] Now that you have encrypted them, do you decrypt them before comparing them to the ones inputted through the form? Nope, that would be a bit more complicated than we need to make it. Simply encrypt the inputted username and password and compare those to the already encrypted values in the file. But what about decryption - can it be done? Yes, but to keep on the safe side, we can live without it; it may not be lawful in some countries to present a method that allows people to decrypt too! *Wonders why* Perhaps, it's safer to let the script decide what the salt is. In our example, let's just take the first two letters of the inputted values (username and password) and use that as the salt to decrypt each respectively. To do this, we can use another function called substr, which refers to substring (taking only a part of a string - after all, what is a string other than an array of characters?). It basically returns a substring from a given expression: $substring = substr($expression,$offset,$length); Offset denotes how far from the beginning of the string to begin the substring. Length denotes the length of the substring (number of characters) to return. If you omit the length value, it will return everything after offset to the end of the string. For example, let our expression be "hello". $expression = "hello"; Then substr($expression,0,1); would return "h" since you specified an offset of zero and only one character from the string to be returned.
$substring = substr($expression,1,1);
$substring = substr($expression,0,2);
$substring = substr($expression,1,2); Offset and length can have negative integer values as well! What would that do? A negative offset would be taken to mean that the script is to count the offset from the end of the string, not the beginning which is what a positive integer value would do.
$substring = substr($expression,-3,1); A negative length value would tell the script to leave that many characters off the end of the string.
$substring = substr($expression,0,-2); Back to why this is useful: we can take a substring value from the original input and use that to encrypt the data: $encryptedPassword = crypt($password,crypt($password,0,2)); In the above line, crypt would return the first two letters of the password as the salt for the crypt device. So if it is encrypted, don't forget to encrypt the inputted values before trying to compare :) Last Updated August 3, 1999
|
||||||||||
©1999 Team 26297 "Ad Infinitum Web." All rights reserved. Any reproduction of this document for commercial or redistribution purposes without the permission of the author is forbidden.