Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Opa.. fiz uma classe, para melhorar um pouco a segurança na questão de ataques brute force. Feita e testada no PHP4.
downloads:download(imagens)
Qualquer erro, por favor poste aqui.
class.php
<?php//==================================// Anti Brute Force Attacks//==================================class bruteforce{ var $ip; // ============================================= // Atualiza no DB (como banido) // ============================================= function ban_bf($now){ $tries = $this->count_tries($this->ip); // tentativas feitas pelo usuario $check = $this->select_bf($this->ip); // checa se esta no BD settype($check, "boolean"); // define $check como boolean settype($tries, "int"); // define $tries como integer if ($tries == 3){ if ($check){ $query = mysql_query("UPDATE `bruteforce` SET `banned_until` = '".slashes($this->plus_min('5'))."' WHERE `bruteforce`.`ip` = '".slashes($this->ip)."'"); } } } // ============================================= // Insere uma tentativa, se for a terceira bane // ============================================= function insert_bf($user, $now){ $tries = $this->count_tries(); // tentativas feitas pelo usuario $check = $this->select_bf(); // checa se esta no BD settype($check, "boolean"); // define $check como boolean settype($tries, "int"); // define $tries como integer switch ($tries){ case "0": $query = mysql_query("INSERT INTO `bruteforce` (user, IP, ban, date) VALUES ('".slashes($user)."', '".slashes($this->ip)."', '1', '".server_date()."')"); break; case "1": $query = mysql_query("UPDATE `bruteforce` SET `ban` = '2', `date` = '".server_date()."' WHERE `bruteforce`.`ip` = '".slashes($this->ip)."'"); break; case "2": $query = mysql_query("UPDATE `bruteforce` SET `ban` = '3', `date` = '".server_date()."' WHERE `bruteforce`.`ip` = '".slashes($this->ip)."'"); $this->ban_bf($now); break; } } // ============================================= // Conta quantas vezes errou login // ============================================= function count_tries(){ $tries = $this->select_bf(); // checa se esta no BD settype($tries, "boolean"); // define $tries como boolean $query = mysql_query("SELECT `ban` FROM `bruteforce` WHERE `ip` = '".slashes($this->ip)."'"); $tries_num = @mysql_result($query,0); return $tries_num; } // ============================================= // Verifica se o usuario JÁ está no BD // ============================================= function select_bf(){ $query = mysql_query("SELECT * FROM `bruteforce` WHERE `ip` = '".slashes($this->ip)."'"); $rows = mysql_num_rows($query); if ($rows == 1){ return(true); } else { return(false); } } // ============================================= // Adiciona minutos, ao horario em que foi banido // ============================================= function plus_min($minutes){ $timestamp = mktime(date("H")-3, date("i")+$minutes, date("s"), date("m"), date("d"), date("Y")); return gmdate("Y-m-d H:i:s", $timestamp); } // ============================================= // Verifica se o usuario está banido // ============================================= function check_banned($type){ switch ($type){ case "all": $query = mysql_query("SELECT * FROM `bruteforce` WHERE `ip` = '".slashes($this->ip)."' AND `ban` >= '1'"); $rows = mysql_num_rows($query); if ($rows == 1){ return(true); } else { return(false); } break; case "tries": $query = mysql_query("SELECT * FROM `bruteforce` WHERE `ip` = '".slashes($this->ip)."' AND `ban` != '3'"); $rows = mysql_num_rows($query); if ($rows == 1){ return(true); } else { return(false); } break; case "ban": $query = mysql_query("SELECT * FROM `bruteforce` WHERE `ip` = '".slashes($this->ip)."' AND `ban` = '3'"); $rows = mysql_num_rows($query); if ($rows == 1){ return(true); } else { return(false); } break; } } // ================================================ // Verifica se o IP da Session é = ao IP atual // ================================================ function check_userip() { if ($this->ip != $_SESSION['old_ip']){ $this->ip = $_SESSION['old_ip']; } } // ================================================ // Verifica se já passou o tempo de espera // ================================================ function bruteforce($ip){ $this->ip = $ip; // define o IP do usuario na session if (!isset($_SESSION['old_ip'])){ $_SESSION['old_ip'] = IP(); } $this->check_userip(); $query = mysql_query("SELECT * FROM `bruteforce` WHERE `ban` = '3' AND `banned_until` <= '".server_date()."'"); while ($line = mysql_fetch_array($query)){ $usuario = $line["IP"]; $this->remove_bf($usuario); } $query = mysql_query("SELECT * FROM `bruteforce` WHERE `ban` != '3' AND DATE_ADD(date, INTERVAL 15 MINUTE) <= '".server_date()."'"); while ($row = mysql_fetch_array($query)){ $user = $row["IP"]; $this->remove_bf($user); } } // ================================================ // Remove o Usuário do BD // ================================================ function remove_bf($ip){ $query = mysql_query("DELETE FROM `bruteforce` WHERE `bruteforce`.`ip` = '".slashes($ip)."'"); }}/* * ************************ * Fim da Classe * ************************ */?>
functions.php
// pega o horário do SERVIDOR, nao o do visitantefunction server_date(){ $timestamp = mktime(date("H")-3, date("i"), date("s"), date("m"), date("d"), date("Y")); return gmdate("Y-m-d H:i:s", $timestamp);}// Escapar Stringfunction slashes($string) {$string = (!get_magic_quotes_gpc()) ? mysql_escape_string($string) : $string; return $string;}// IP do usuáriofunction IP() {if(isset($_SERVER['HTTP_X_FORWARDED_FOR']) && strpos($_SERVER['HTTP_X_FORWARDED_FOR'],',')) {$IP = explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']);} elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {$IP = $_SERVER['HTTP_X_FORWARDED_FOR'];} else {$IP = $_SERVER['REMOTE_ADDR'];}return $IP; }// ANTI SQL INJECTIONfunction SQLInject($txt){ $inject=0;$badword = array(" select","select "," insert"," update","update "," delete","delete "," drop","drop "," destroy","destroy "); for($i=0;$i<sizeof($badword);$i++){ if(substr_count($txt,$badword[$i])!=0){ $inject=1; } }$charvalidos = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ÁÀÃÂÇÉÈÊÍÌÓÒÔÕÚÙÜÑáàãâçéèêíìóòôõúùüñ!?@#$%&(){}[]:;,.-\/ "; for($i=0;$i<strlen($txt);$i++){ $char = substr($txt,$i,1); if(substr_count($charvalidos,$char)==0){ $inject=1; } } return($inject);}
install.sql
CREATE TABLE bruteforce (action_id INT NOT NULL AUTO_INCREMENT ,user VARCHAR( 255 ) NOT NULL ,IP VARCHAR( 26 ) NOT NULL ,ban INT NOT NULL ,date DATETIME NOT NULL ,banned_until DATETIME NOT NULL ,PRIMARY KEY ( action_id ));
exemplo.php
<?phpsession_start();require_once("lib/class.php");require_once("lib/functions.php");if (isset($_SESSION["login"])){ echo("<center>".htmlentities("Você já está logado como")." <b>". $_SESSION['user'] ."</b>! Para logar-se com outro usúario, favor faça um logout!</b></center>");} else{$bf = new bruteforce(IP());$banned = $bf->check_banned('ban');if ($banned){$query = mysql_query("SELECT * FROM `bruteforce` WHERE `ip` = '".IP()."'"); while ($line = mysql_fetch_array($query)){ $banned_upto = substr($line["banned_until"], 10); echo("<div align=\"center\">Você foi bloqueado por 5 minutos. <br /> Tente logar denovo às: <strong>".$banned_upto."</strong> de hoje</div>"); }} else {if (isset($_POST['act'])){$username = $_POST['user'];$passwd = $_POST['pass'];$image = (int)$_POST['image'];$imageverify = (int)$_POST['imageverify'];$key = '2a2cf8gk68gj67gf784kh69fo6';$time = time();$ip = $_SERVER['REMOTE_ADDR'];$rand = rand(0,10000); if (empty($username) || empty($passwd) || empty($imageverify)) { echo("<div align=\"center\">"); echo("<b>Por favor, preencha todos os campos!</b><br>"); echo("<a href=\"java script:self.history.go(-1)\">Voltar</a>"); echo("</div><br />"); return; } if(SQLinject(STRTOLOWER($username)) || SQLinject(STRTOLOWER($passwd))) { echo("<div align=\"center\">"); echo("<b>Tentativa de Hack!</b><br>"); echo("<a href=\"java script:self.history.go(-1)\">Voltar</a>"); echo("</div><br />"); $bf->insert_bf($username, IP(), server_date()); return; } if (strlen(trim($username)) < 4 || strlen(trim($username)) > 23) { echo("<div align=\"center\">"); echo("<b>".htmlentities("Seu nome de usuário deve conter entre 4 e 23 caractéres!")."</b><br>"); echo("<a href=\"java script:self.history.go(-1)\">Voltar</a>"); echo("</div><br />"); $bf->insert_bf($username, IP(), server_date()); return; } if (strlen(trim($passwd)) < 4 || strlen(trim($passwd)) > 23) { echo("<div align=\"center\">"); echo("<b>".htmlentities("Sua senha deve conter entre 4 e 23 caractéres!")."</b><br>"); echo("<a href=\"java script:self.history.go(-1)\">Voltar</a>"); echo("</div><br />"); $bf->insert_bf($username, IP(), server_date()); return; } if ($image != $imageverify) { echo("<div align=\"center\">"); echo("<b>".htmlentities("Verificação de Imagem Incorreta!")."</b><br>"); echo("<a href=\"java script:self.history.go(-1)\">Voltar</a>"); echo("</div><br />"); $bf->insert_bf($username, IP(), server_date()); return; } $passwd = md5($passwd);$query = mysql_query("SELECT `users`.`username`, `users`.`passwd` FROM `users` WHERE `users`.`username` = '".slashes($username)."' AND `users`.`passwd` = '".slashes($passwd)."'");$num = mysql_num_rows($query); if ($num == "0") { echo("<div align=\"center\">"); echo("<b>".htmlentities("Nome de Usuário/Senha não Existentes ou Incorretos!")."</b><br>"); echo("<a href=\"java script:self.history.go(-1)\">Voltar</a>"); echo("</div><br />"); $bf->insert_bf($username, IP(), server_date()); return; } $md5user = md5($_POST['user']);$md5pass = md5($_POST['pass']);$md5key = md5("2a2cf8gk68gj67gf784kh69fo6");$md5time = md5(time());$md5ip = md5($_SERVER['REMOTE_ADDR']);$md5rand = md5(rand(0,10000));$_SESSION['login'] = array("user" => $md5user, "key" => $md5key, "time" => $md5time, "ip" => $md5ip, "rand" => $md5rand);$_SESSION['user'] = serialize($username);echo("<meta http-equiv=\"refresh\" content=\"0; URL=default.php?link=home\">");} else {?><table align="center" width="300"> <tr> <td><fieldset width="300"><legend width="100" align="center"> <font color="#0066cc"><b> Autenticação</b></font></legend> <div align="center"><form name="login" method="post" action="exemplo.php"> <b>Usuário:</b> <br /> <input type="text" name="user" size="12" maxlength="24" class="input_text"><br /> <b>Senha:</b><br /> <input type="password" name="pass" size="12" maxlength="23"><br /><table style="margin: 5px" cellspacing="0" cellpadding="0" align="center"><?php//Verificacao de Imagem$randomnumone = rand("0", "9");$randomnumtwo = rand("0", "9");$randomnumthree = rand("0", "9");$randomnumfour = rand("0", "9");$randomnumfive = rand("0", "9");$randomnumsix = rand("0", "9");$total = $randomnumone." ".$randomnumtwo." ".$randomnumthree." ".$randomnumfour." ".$randomnumfive." ".$randomnumsix;$form = $randomnumone.$randomnumtwo.$randomnumthree.$randomnumfour.$randomnumfive.$randomnumsix;$exploded = explode(" ", $total);$one = 0;$two = 0;$three = 0;$four = 0;$five = 0;$six = 0;echo("<tr><td align=\"center\" colspan=\"6\" style=\"margin-top: 3px;\"><strong>".htmlentities("Verificação de Imagem")."</strong></td></tr>");while($exploded['0'] != $one){ $one++;}if($exploded['0'] == $one){ echo("<tr><td style=\"border-bottom: 2px #000000 solid; border-left: 2px #000000 solid; border-top: 2px #000000 solid;\"><img class=\"news\" src=\"../templates/images/autenticacao/{$one}.gif\"></td>");}while($exploded['1'] != $two){ $two++;}if($exploded['1'] == $two){ echo("<td style=\"border-bottom: 2px #000000 solid; border-top: 2px #000000 solid;\"><img src=\"../templates/images/autenticacao/{$two}.gif\"></td>");}while($exploded['2'] != $three){ $three++;}if($exploded['2'] == $three){ echo("<td style=\"border-bottom: 2px #000000 solid; border-top: 2px #000000 solid;\"><img src=\"../templates/images/autenticacao/{$three}.gif\"></td>");}while($exploded['3'] != $four){ $four++;}if($exploded['3'] == $four){ echo("<td style=\"border-bottom: 2px #000000 solid; border-top: 2px #000000 solid;\"><img src=\"../templates/images/autenticacao/{$four}.gif\"></td>");}while($exploded['4'] != $five){ $five++;}if($exploded['4'] == $five){ echo("<td style=\"border-bottom: 2px #000000 solid; border-top: 2px #000000 solid;\"><img src=\"../templates/images/autenticacao/{$five}.gif\"></td>");}while($exploded['5'] != $six){ $six++;}if($exploded['5'] == $six){ echo("<td style=\"border-right: 2px #000000 solid; border-bottom: 2px #000000 solid; border-top: 2px #000000 solid;\"><img src=\"../templates/images/autenticacao/{$six}.gif\"></td>");}?> </td> </tr> <input type="hidden" name="image" value="<?php echo $form; ?>" /> <tr> <td align="center" style="margin: 5px;" colspan="6"> <input style="margin: 3px;" type="text" maxlength="6" name="imageverify" /> </td> </tr></table> <input name="" type="reset" value="Limpar" /> <input name="act" type="submit" value="Enviar" /> <br /> </td></tr></table></form></div></fieldset> } }}?>Eu queria saber se este código prevê a eliminação de registros obsoletos do banco de dados. Por exemplo:Alguém tenta as três vezes, é banido e para continuar tentando muda o nº de IP. Imagine que esta pessoa efetue essa operação por 10 vezes. São 10 IPs diferentes armazenados no banco.Será que seu código consegue eliminar estes registro inválidos do banco de dados ou esses registros vão se acumulando indefinidamente.Obrigado.
os registros são apagados, depois que se completa os 5 minutos, ele apaga... caso o usuario erre 2 vezes com o ip, e nao tente denovo ai ele fika, mas estou fazendo uma nova parte do código que apaga.Como aqui eu uso mySQL 4, e nao tem como fazer um store procedure ou trigger na versao q eu tenho, entao ele soh faz isso, quando um visitante visita a página.
Eu não entendi como você exclui os IPs adicionais.Se uma pessoa tenta se logar com 10 logins e 10 IPs diferentes. você só vai excluir o último IP após o período de ban se a pessoa manter o mesmo IP e tentar refazer o login, não é isso? Ou será que toda pessoa que se loga, você aproveita para excluir todos os IPs que já ultrapassaram o período de ban.
por exemplo, ele exclui pelo IP do kra, e soh exclui após os 5minutos terem se passado, e cada vez que alguem entra nessa página, ele exclui todos os que já passaram do tempo.
Bacana! http://forum.imasters.com.br/public/style_emoticons/default/clap.gif
tem alguma forma de impedir que o usuario tente mais vezes com ip diferente.. no caso de reconectar o modem e fazer limpeza de cookies.. talves uma identificação que nao mudace quando uma operação é realizada...
existe alguma forma?
obrigado
e parabeins pela classe. mtu boa. http://forum.imasters.com.br/public/style_emoticons/default/clap.gif
talvez ateh tenha algum modo...mas o kra teria q reconectar centenas de vezes, pois soh tem 3 chances... vo procurar se acho alguma maneira
**Novidades:Nova versão:Novidades -> agora ele apaga registros q jah passaram 15 minutos, por exemplo: o kra errou 2 vezes e n tentou mais, quando se passa 15minutos ele deleta do banco de dados... mudada o nome da classe check_time para bruteforce, agora ele jah checa sozinho, nao precisa mais fazer $checktime = $bf->checktime();eh isso por enquanto, depois eu faço novas atualizações
muito bom ;)
Como é que faz para adaptar para um sistema simples de login ?
Olá gente alguém tem essa função para PHP 5 ????
legal....!