2

i'm developing a PHP web application and the main focus of the app is security. Until now i've stored the authentication data into 2 cookies:

  • one cookie for a unique hash string (30 chars)
  • one cookie for a unique id (the primary key of the mysql database table which holds the cookie info and user id)

Db tables look like this:

  • Users (user_id, username, password)
  • Cookies (cookie_id, user_id, hash, time, ip)

When a user visits the page the app checks for existing cookies (cookie check) on the client and compares them to the database table Cookies. If the hash string and the id match, the session is extended and if they don't, the session is destroyed (if exists) and the user is prompted to login. It also checks if the session expired by comparing the current time stamp to the time stamp of the last activity.

When the user logs in a hash strings is generated and stored in the database (the current time stamp and IP is also stored). The primary id of the newly generated row and the hash string are then stored into two cookies and used for authentication.

I would like to implement additional security to prevent dictionary or brute force attacks, by throttling the login and cookie check attempts. I'd like to achive that when the user fails N times to login or to validate cookies that he gets blocked for 20 minutes. But if i do this using the IP i would potentially block every user using that IP.

I could lock the specific user account when there are more than X failed attempts, but the problem is when the attacker doesn't supply a valid username (so i would have to block the whole IP for N minutes).

The login form has also a captcha check, but that just slows down a attack (nothing compared to denying login attempts for X minutes).

  • Is there any other way of denying login attempts without blocking out the whole network using that IP?
  • Should i bother with denying login attempts when there are N failed cookie checks?
  • If the users cookies are stolen, i use the IP in Cookie table to prevent reusing it, so the cookies are usable only from the same IP as the users. Is this secure or should i do it somehow else?

Thanks in advance,

PS: all passwords in database are hashed, the cookie values are encoded before used in a db query (so injections aren't possible).

blejzz
  • 3,349
  • 4
  • 39
  • 60

2 Answers2

1

Security is not achieved by complicated code, but by simplicity. Instead of inventing your own session handling, you should use php's builtin one.

Also, there's no reason to store the user name in a cookie, doing so only makes your application prone to all kinds of vulnerabilities caused by mismatch between user and session. Instead, store the user's ID with each session entry.

You should rate-limit authentication attempts (i.e. password entries), possibly with CAPTCHAs, or better yet, not store passwords at all and use OpenID. Also, just hashing passwords is not enough; make sure to use a salt.

Community
  • 1
  • 1
phihag
  • 278,196
  • 72
  • 453
  • 469
  • i store only a hash and a cookie table id, not usernames and not even user ids. The reason i don't use sessions is they get destroyed when the browser is closed. – blejzz Jul 16 '11 at 22:11
  • @Simos Mikelatos The more code you write, the bigger the chance that there's a bug in there. Storing sessions in two locations is one of those things that even if done right provide negligible security benefits, but are prone to programming errors. – phihag Jul 16 '11 at 22:13
  • @jernej You can configure cookie lifetime with [session.cookie_lifetime](http://php.net/manual/en/session.configuration.php#ini.session.cookie-lifetime), so that's really not an argument for writing your own session handling code. And you're extremely likely to mess something up, for example drastically reducing entropy of the session IDs. – phihag Jul 16 '11 at 22:16
1

I'm developing a PHP web application and the main focus of the app is security

If you care about security You should not implement authentication yourself, but use OpenID just like stackoverflow.com => http://www.codinghorror.com/blog/2008/05/openid-does-the-world-really-need-yet-another-username-and-password.html

LightOpenID is a very nice/easy openID library => http://gitorious.org/lightopenid

I would like to implement additional security to prevent dictionary or brute force attacks, by throttling the login and session check attempts. I'd like to achive that when the user fails N times to login or to validate cookies that he gets blocked for 20 minutes. But if i do this using the IP i would potentially block every user using that IP.

P.S: I would use OpenID, but below I will tell how I would do this.

The blocking of IP's is bad like you are saying, because a lot of users share them same IP via NAT. but when you suspect brute-force attack(from IP) I would just let them authenticate only if they enter the captcha correctly. This way the users behind NAT can still login while the hacker is shut out.

The login form has also a captcha check, but that just slows down a attack (nothing compared to denying login attempts for X minutes).

When you protect your site with captcha, hacking your site is almost impossible if length of passwords is long enough(you should enforce this). Because let's say you can solve a captcha in 5 seconds, which comes to 12 captchas per minute. What you could do is lock out an account when attempted a number of times. You sent a very long string to the users account which he can use to set a new password

Alfred
  • 60,935
  • 33
  • 147
  • 186
  • unfortunately OpenID is not an option. Brute forcing can be done with guessing the username and the password or by guessing the session id which is stored in a cookie. So when guessing the password with a known username i can lock the account, but the problem is when the username isn't known. So i can lock only the IP (locking the whole network), which i'm trying to avoid. – blejzz Jul 16 '11 at 23:39
  • Why is OpenID not an option. To crack a password you need to try a lot of times for the same username. Otherwise you can never brute force hack this(probability is zero). captcha stops bruteforcing. Then hackers move along to login-system which does not use captcha... – Alfred Jul 17 '11 at 00:00
  • It's for a customer and the login system is already implemented. I agree that using captcha at login can slow down brute force or even stop it. But what about when checking for existing session/cookies, is it possible to brute force through that? Do i need to limit max session checks fails for an IP? Or could i use a different approach? How does openID cope with that? – blejzz Jul 17 '11 at 11:37
  • cookie(session is also cookie) can be cleared. Big sites like google etc don't use captcha because they are user friendly, but because it is the only way to stop attack. – Alfred Jul 17 '11 at 15:46
  • i understand that perfectly, what i don't understand is how to block brute forcing the session id without blocking the whole IP. When the user logs in (has to enter his user + password) u just show the captcha when there are more then 2 failed attempts per IP. But u can't do that when validating the session/cookie (when user already logged in).. if u would block the IP u would block users that are already logged. Locking an account isn't really good on a bidding site where there are 3 users bidding for the purchase, because u could just lock out the other user in the last minute :) – blejzz Jul 17 '11 at 19:39
  • I think understand your question. You are afraid somebody tries to brute force the session_id. first those are very strong. You are "kind of" blocking IP, but not really because he needs to provide captcha before you do any checking for that session(id). Instead of blocking IP completely, which could stop legitimate users from entering your site completely. You would make them pass a captcha first. Maybe my answer about sessions could help you out a bit => http://stackoverflow.com/questions/6717214/sessions-vs-temp-cookies/6717718#6717718 – Alfred Jul 17 '11 at 21:32
  • so your anwser would be to just show the captcha if the IP has more than X failed attempts when login, without locking the account/IP? (facebook has the same principle or i didn't test long enough) – blejzz Jul 17 '11 at 22:23
  • @jernej Facebook, Google(I experience this myself). All big sites use this approach because then hacker can't hack, but legitimate user on same IP can still use the site. That user has a little bit negative experience(entering captcha), but that is the price he has to pay for security. Also validating should take some time. This because phpass(http://www.openwall.com/phpass/) which you should use takes time. This way brute forcing won't work anyway. The user won't notice 500 ms delay, but a hacker can only do 2 hacks per second. But with captcha he can't even do that ;) – Alfred Jul 17 '11 at 22:36
  • one more thing.. what if an IP has X failed session validations in the last Y minutes, use captcha there also? If so then if there are 2 users with the same IP, one logged and the other one trying to hack the session validation. When the attacker will fail X times then they both will be prompted to enter captcha. Any solution for that? Thank you, you have been very helpful :) – blejzz Jul 17 '11 at 23:54
  • @jernej it is almost impossible to hack session_id(). I don't you should worry to be much about that => See http://pastebin.com/z7Bw5SQU for some more information. But what you could do for the logged in user is store unique identifier(use for example http://php.net/manual/en/function.uniqid.php) inside cookie and also session(use http_only flag to protect against stealing from javascript => => http://www.codinghorror.com/blog/2008/08/protecting-your-cookies-httponly.html). The hacker does not have that unique id inside his cookie so access is denied. Hope this is clear. – Alfred Jul 18 '11 at 02:13