I wish to ask if the code written below has any holes (probably it will be useful for someone else). This code checks if more than 5 attempts within the last 5 minutes were made to login. Checked by ip and by userid. Every attempt to log in is stored in history table (MySQL).
history table is needed only for the purpose of CAPTCHA displaying.
ENGINE=InnoDB is chosen. (Do you recommend to use MyISAM for better performance? Would you recommend to put index on Time or userid or remote_addr?)
Any suggestions about optimization? Possible holes?
Thank you.
$query1="SELECT id FROM history WHERE (Time>date_sub(now(), interval 5 minute)) AND remote_addr='".ip2long($_SERVER['REMOTE_ADDR'])."' limit 6"; //limit 6 is for performance, 6+ means 6, we only care if it less than 5
$result1=mysql_query($query1);
//so we know mysql_num_rows($result1)
$query2="SELECT id FROM history WHERE (Time>date_sub(now(), interval 5 minute)) AND userid='".$userid."' limit 6";//limit 6 is for performance, 6+ means 6, we only care if it less than 5
$result2=mysql_query($query2);
//so we know mysql_num_rows($result2)
$attempts=0;//we want to set up $attempts=maximum of (mysql_num_rows($result1), mysql_num_rows($result2))
if($result1) {
$attempts=mysql_num_rows($result1);
}
if($result2 && $attempts<mysql_num_rows($result2)) {
$attempts=mysql_num_rows($result2);
}
//if $attempts is more than 5, then CAPTCHA should be displayed, if less then it should not
P.S. Do you still recommend to put usleep(100000) or any other method to prevent bruteforce in case if somebody writes the algorythm one day (until captcha again gets stronger) to hack captchas?
Added: thank you for asking, yes, $userid is cleaned from bad symbols.
No security issues if $userid is sanitized, but I would offer the the following changes to make the code more efficient: Use MySQL’s COUNT function instead of returning the six ID numbers. If you don’t need to use the IDs for anything, don’t retrieve them. Also, I see no reason to query the database twice. Pare it down a bit.
The code below is shorter, faster and safer (with
mysql_real_escape_string()— I’d recommend taking a look at that function). We eliminate a query, a couple ofifstatements and save on sending the unnecessary data across the network: