Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW

comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

Looking for feedback on the security model that I have for a particular site. We've been asked to encrypt only the login process (SSL). This site is for an administration console and will only have a few users. They are required to have cookies enabled. Here's basically how it works:

The user enters a username/password combination. This is sent over an ssl connection to the authentication script. The password is hashed using Digest::MD5 and a salt that is read from a non-web accessible file. This is compared to the hashed password in the database. If they don't match, they are redirected to the login screen up to seven times, after which they are locked out until an administrator unlocks them. If successful, a digest is created with the following algorithm:

sub _create_session_digest { # Please note that we will compare the digest against what's in th +e database rather than # recompute. It's quite possible for someone's ip address to chan +ge with every request. my $self = shift; my $md5 = new Digest::MD5; my $remote = $ENV{ REMOTE_ADDR } . $ENV{ REMOTE_PORT } . $self->{ +_salt }; my $id = $md5->md5_base64( time, $$, $remote ); $id =~ tr|+/=|-_.|; # Make non-word characters URL-friendly $id; }

This digest is returned as a cookie. Subsequent accesses to the admin console will return the digest and compare it to the database. If this takes too long, their session times out (controlled by the script, not the cookie) and they must relogin. If the digest matches, a new digest is created, stored in the database, and sent back in a cookie. Except for the initial SSL connection when the username and password are submitted, they will never again be sent. Here's the main code that controls this:

# Everything in ALL CAPS is a constant sub validate_and_get_new_cookie { my ( $self, $cgi, $user, $pass ) = @_; my $cookie = $cgi->cookie( SESSION_COOKIE_NAME ); # delete sessions older than that session ID's allowed timeout $self->_clear_old_session( $cookie ); if ( defined $user and defined $pass ) { # they're submitting a username and password, so let's try to +log them in my $attempts = $self->_count_login_attempts( $user ); $self->_lockout if $attempts >= MAX_LOCKOUT_ATTEMPTS; my $db_pass = $self->_get_password( $user ); my $user_pass = $self->_create_digest_from_password( $pass ); if ( $db_pass eq $user_pass ) { return $self->_create_digest_cookie( $user ); } else { my $attempts = $self->_update_attempts( $user ); $self->_log_bad_attempt( $user, $pass ); $self->_lockout if $attempts >= MAX_LOCKOUT_ATTEMPTS; print $q->redirect( LOGIN_PAGE ); } } else { # no user or password, so we'll try to validate with the cooki +e my ( $user, $active ) = $self->_get_digest_info( $cookie ); if ( ! defined $user or ! $active ) { # didn't get a user name or they've been inactive too long print $q->redirect( LOGIN_PAGE ); } else { return $self->_create_digest_cookie( $user ); } } }

In the future, I plan to add a 'bogusLogin' table to the database. The intent is to even lockout non-existent user IDs after MAX_LOCKOUT_ATTEMPTS so that crackers can't use the lockout feature to determine if they have a valid user id. Have I overlooked anything?


Vote for paco!

Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

In reply to CGI Security Advice Sought by Ovid

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?

What's my password?
Create A New User
Domain Nodelet?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (2)
As of 2023-03-21 22:56 GMT
Find Nodes?
    Voting Booth?
    Which type of climate do you prefer to live in?

    Results (60 votes). Check out past polls.