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 anythi开发者_运维技巧ng 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.:
$hash = sha1($username.$userip.$timestamp.$secret);
Where $secret
is never communicated outside your script. If you want, you can store the public data to the cookie:
$cookie = implode("/", array($username, $timestamp, $hash));
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...
Well all that doesn't really matter in a man-in-the-middle attack. a Secure Socket Layer is very recommended if your dealing with sensitive information.
Use the LDAPv3 Transport Layer Security (TLS) extension for a secure connection.
Also, log the http-user-agent to differ between computers on the same network.
Locking the user accounts to prevent bruteforcing is always a good idea. Make sure to deny the IP address/user agent combination and not only the ip address.
Now they can't capture the info when your sending it, and they can't fake the cookie information. For that part, it's pretty secure. There could be other factors though, but as i don't know them, it isn't relevant.
精彩评论