--- Ryan Davis <[EMAIL PROTECTED]> wrote:
> OK, I know this is getting a little off-topic, but I think security is a big
> issue, especially with newbies like myself, and deserves some good
> discussion. Also, there's probably not a perl-cgi-beginners-security list,
> nor should there be.
> 
> I looked at the perlmonks article, and had some trouble making sense of it,
> but here is my idea:
> 
> 1) User first signs up, gives a password.  The password is passed through
> MD5
> to make a digest, and the digest is stored in a password database.

Yes.
 
> 2) A session ID is generated and written to the cookie (instead of the
> password), and to a database.  The ID is itself digest based on username,
> time, and another string, $rand.

Slightly different from how I'm doing it, but this is perfectly fine.  I include some 
other stuff,
but I might want to add the username to my digest computation (NOT to the cookie).  
Thanks for the
idea!

> 3) The script reads the session ID from the cookie, compares it to the
> database, and if it is found, then the user is considered logged in

Almost.  Once the first digest is created, the user is then considered logged in.  
Later, when the
script reads the session ID from the cookie, it compares it with the digest and, if 
they match,
the user is considered to be *still* logged in.  This may be what you meant, but I 
wanted to make
sure.

> 4) When the user logs out, the session ID is deleted from the DB, and any
> other session IDs older than, say, 1 day are deleted from the DB as well, to
> take care of people who don't log out properly.

Don't depend on the user logging out.  Many of them will simply close their browser 
and not
logout.  In my code, when I check the digest, I also check a timestamp in the 
database.  If that
timestamp is greater than the "inactive" time allowed, then I log them out 
automatically.  Just
make sure that you don't depend on the cookies expiration time as you cannot control 
the whether
the user agent abides by this expiration time.

Later, when you create the next session ID and store it in the database, don't forget 
to update
the timestamp in the database.

> Is making the session ID a digest just extra processing, or does it have a
> point?

You could generate a random session ID and this would be faster than creating a 
digest.  I like
the digest method because, if done properly, it's much less likely to generate a 
duplicate session
ID.

Also, every time I read the cookie, I generate a new session ID, store it in the 
database, and
return the new ID.  That way, if someone is sniffing the connection and grabs a 
session ID, they
are less likely to hijack a session by supplying that session ID.  Further, with the 
timeout
feature, if they sniff the ID and try to use it too late, they still can't get in.

The only way to hijack the session with this method is to sniff the session ID and 
submit it as a
cookie *before* the real user has a new ID used.

One final note, despite what it says on the Perlmonks link that I supplied, the 
*entire* admin
console is now encrypted (we convinced the client that this was a good idea).  
Further, the cookie
that is sent is now a "secure" cookie and can only be sent over a secure connection.  
As a result,
even though it's tough to crack the cookie info, it's now much tougher because it's 
been
encrypted.  Here's the CGI.pm code that I use to generate the cookie:

    my $cookie = $q->cookie( -name   => SESSION_COOKIE_NAME,
                             -value  => $value,
                             -path   => '/',
                             -secure => 1 );

The SESSION_COOKIE_NAME is a constant to ensure that the cookie naming doesn't get out 
of synch. 
The $value is the digest and the "-secure => 1" instructs the user agent to only 
return the cookie
over a secure connection.

> My application is for a student group I'm involved in, and I'm guessing
> other student groups might enjoy trying to hack in and put bad data into the
> database I'm interacting with, to make my group look bad.  Kinda reminds me
> of West Side Story, but a lot geekier and with less singing.

I dunno.  Singing geeks sounds cool to me :)

If you're curious about the login table, it's something like this:

user     varchar(20)
password char(22)    (because the digest created is always 22 characters long)
time     datetime    (this is the time the last cookie was sent)
active   bit         (if they get locked out or their time expires, I set this to zero)
session  char(22)    (sessionID digest)
timeout  int         (number of minutes they may be 'inactive')
attempts int

As for the "attempts" field, if a particular user name fails a login, I increment 
attempts by one.
 After 7 attempts, they are permanently logged out until an admin resets that to zero. 
 If they
successfully login, I set attempts back to zero.

Let me know if you have any questions.

Cheers,
Curtis Poe

=====
Senior Programmer
Onsite! Technology (http://www.onsitetech.com/)
"Ovid" on http://www.perlmonks.org/

__________________________________________________
Do You Yahoo!?
Make international calls for as low as $.04/minute with Yahoo! Messenger
http://phonecard.yahoo.com/

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to