I want to limit the failed login attempts. For example, if a specific user attempt to login with wrong username or password 4 times, i should show the CAPTCHA 4th time instead of blocking for some specific time, and keep showing CAPTCHA unless he supplies valid username and password. Once the user has successfully logged in, the login attempt is reset to ZERO.
Is the idea of checking the username instead of IP address OK in security point of view? Can this approach be implemented without using database?, as I think I don't need to store time because i will just show recaptcha?
Please give your opinion.
You don't want to use the database for the 'number of failed logins'-check? Then just use a cookie and check it. Sure, they can remove it, but it's a hassle.
However, I suspect that you already are getting the username and password from the database, why not also fetch the last number of failed logins while you are at it?
if (isset($_POST['submit_login'])) {
if (isset($_POST['username']) && isset($_POST['password'])) {
$username = mysql_real_escape_string($_POST['username']);
$password = mysql_real_escape_string($_POST['password']);
// id = unique primary key
$rs = mysql_query('SELECT id,Username,Password,Failed_logins,IP_address FROM Users WHERE Username = '.$username.'');
$num = mysql_num_rows($rs);
if ($num > 0) {
// I would add a password hash here to $password, and check against the hashed Password from the database
// But let's check the clean passwords
$row = mysql_fetch_array($rs);
if ($password == $row['Password']) {
// Successful login, set session or whatever you need
// Reset failed logins
mysql_query('UPDATE Users SET Failed_logins = 0 WHERE id = '.$row['id'].'');
header('location: success.php');
} else {
// Failed password check
if ($row['Failed_logins'] > 3) {
// Redirect to captcha
header('location: captcha.php');
} else {
$ip = $_SERVER['REMOTE_ADDR'];
if ($row['IP_address'] != $ip) {
// New ip adress, reset failed logins
$failed_logins = 0;
} else {
// Increment failed logins
$failed_logins = $row['Failed_logins']+1;
}
mysql_query('UPDATE Users SET Failed_logins = '.$failed_logins.',IP_address = '.$ip.' WHERE id = '.$row['id'].' ');
} // End check Failed_logins > 3
}
} else {
// No such Username found in database
$error = 'no_such_username';
} // End username check from database
} else {
// Either username or password is missing
$error = 'incomplete_form';
} // end check for username and password
} // end main submit_login check
Something like that.
EDIT:
This is really old code and I see some problems with it now. But, at least you should always use PDO (prepared statements) for inserting data in your database.
What are you protecting?
Random user-only content, username.
Banking information (I doubt..) or other sensitive data, IP might be okay, provided you use ranges.
Are you asking how to do it, or which you should use?
You do need time, how would you otherwise determine if an login attempt has expired? If I would fail to login 4 times over a 10 year time span I would get blocked. You want to block those who attempt multiple login attempts in a short time span.
I suggest you use an database - as you will keep an detailed history of logins at the same time. But an memory based solution like memcached could also suffice.
To elaborate on which security to implement: a combination!
Combine the used username and ip address and store them into your database.
- Use the login attempts on your username to directly protect your users from attempts.
- Use the ip address information to observe an detect only, and take action if needed.
You should save the attempts in a database and check the user.
The best way to do this is to use databases.
You need to create a separate table in your database, which would store three variables :
(a) IP address (where the person is trying to log in)
(b) Number of login attempts
(c) date/time (or : current-timestamp)
The ONLY problem with this approach is with the first variable : IP address
What if the person is in an Internet Cafe? Or using public Wi-fi? Or Hotspot? Or, a school? office? etc, etc
If you block the IP address, it affects everybody who is trying to log into your website from that location.
This is not a problem if your website concerns something like a bank, or military installation, or the Pentagon.
But, if your website is a business (buy-and-selling, game, whatever), then blocking a specific address will only piss off your customers!