我想问下面写的代码是否有任何漏洞(可能对其他人有用)。此代码检查在过去5分钟内是否有超过5次尝试登录。由ip和userid检查。每次登录尝试都存储在历史表(MySQL)中。
历史表仅用于CAPTCHA显示的目的。 ENGINE = InnoDB被选中。 (您是否建议使用MyISAM以获得更好的性能?您是否建议将索引放在Time或userid或remote_addr上?)
有关优化的任何建议吗?可能的漏洞? 谢谢。
$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。你是否仍然建议使用usleep(100000)或任何其他方法来防止暴力,如果有人写了一天algorythm(直到验证码再次变强)来破解验证码?
补充:谢谢你的询问,是的,$ userid是从坏符号中清除的。
答案 0 :(得分:3)
如果对$ userid进行了清理,则没有安全问题,但我会提供以下更改以使代码更有效:使用MySQL的COUNT函数而不是返回六个ID号。如果您不需要使用ID,请不要检索它们。此外,我认为没有理由两次查询数据库。把它削减一点。
以下代码更短,更快,更安全(使用mysql_real_escape_string()
- 我建议您查看该功能)。我们消除了一个查询,一些if
语句,并节省了通过网络发送不必要的数据:
$userid = mysql_real_escape_string('...');
$ip = ip2long($_SERVER['REMOTE_ADDR']);
$q = "SELECT COUNT(*) AS cnt FROM history
WHERE Time > date_sub(now(), interval 5 minute)
AND (remote_addr='$ip' OR userid='$userid')
";
$r = mysql_query($q);
// first value, first row (we only get one using count)
$attempts = mysql_result($r, 0, "cnt");
// if $attempts is more than 5, then CAPTCHA should be displayed ...