views:

55

answers:

2

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 ?

A: 

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.

Stephen
These are good comments, although I do not have control over the LDAP deployment I am only responsible for the web application itself. One thing about browser-agents was that I read they can change during an update or add-on which will essentially devalidate the session. Is this something to not worry about and just accept that if a user does this while logged on they will loose their session ?
Chris
@Chris: UA normally doesn't (and ought not) really change during normal operation; installing add-ons or browser update is IMO enough of a change to warrant re-auth; also, it doesn't happen *that* often.
Piskvor
Piskvor is right, don't worry about this. The session has to time out eventually, and most sessions are lost after a browser update.
Stephen
+5  A: 

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...

jmz
Thanks for the comments, as far as your last point though... what if an attacker distributes his attempts across usernames? Although this sounds unusual it seems plausible and I would think limited users to 3 failed attempts daily would prohibit this activity?
Chris
You don't necessarily need the username in failed attempts. Do you really care which account an user was trying to hack?But please **don't make the limit so small**. If you leave your limit to 3 you'll be vulnerable to another kind of DOS: Denial of service for your users.
jmz
So what would you say is a acceptable limit on logins? 3 failed attempts every 10 minutes? 10 failed attempts every 24 hours? Im just not sure where is the sweet spot for something like this
Chris
It depends on the environment you're deploying the software. I'd say, use different strategy against LAN attacks than you use against WAN attacks, if your application is exposed to the general Internet. You mentioned that your application will be used in schools; that speaks of certain type of users and certain type of misuses. Do students benefit from blocking teachers' login? There really is no limits set into stone, but three attempts even I have failed with ssh. Do not mistake human error for an attack.
jmz