I am implementing a web application which is powered on the backend via a soap server/client interaction. The web site is running over https and authentication is being provided by LDAP.
As of now I push all users without a cookie, call it ‘userHash’ for reference to the login page. The login page accepts a username, pass and checks ldap to verify. If it verifies I store in my session the user name, user ip address, and a timestamp.
Lastly I construct a cookie and session hash info:
SESSION['userHash'] = sha1($username.$userip.$timestamp);
cookie['userHash'] = sha1($username.$userip.$timestamp);
This way on any subsequent request I verify the user posses the cookie userHash with matching value to the session[‘userHash’]
Is this setup secure?
Additionally, I want to prevent against brute force attacks and was going to implement a simple DB table to log failed attempts. Currently I am thinking of having:
id | username | timestamp | ipaddress | count
as a table. Is this the best approach or is there a better way? I see for example with this table that if I was to limit failed attempts to 3 every 24 hours, then an attacker has ability to try each username 3 times from the same Ip. (One side note: this application is anticipated to be used on potentially school computer labs which may be on a subnet and thus show me multiple logins from the same IP address so I need to be careful as to when I block based on IP address.)
On the other hand, I got to wondering if there is anything like “denyhosts” for http authentication ?
The hash you create
$hash = sha1($username.$userip.$timestamp);is not secure, as it can be calculated from public information. Username, user IP and timestamp are all public, and available to an attacker. You must add a secret information to the hash, e.g.:Where
$secretis never communicated outside your script. If you want, you can store the public data to the cookie:Then when verifying, use $_SERVER[‘REMOTE_ADDR’] as $userip.
For your second question, you don’t need the count column if you’re already storing the timestamp of a failed attempt. If an attempt comes from the same address for an already failed timestamp, you can reject it because humans don’t do two password entries in a second of time.
Edited to add: Making the limit of failed attempts very small will make your users vulnerable to DOS. School environments especially have plenty of adventurous people, who don’t mind banging a few passwords to try to get into an account. Lock them out after 3 tries, and you lock also the legitimate users…