Jump to content
MagicalTrevor

Anti Brute force Attacks

Recommended Posts

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>  } }}?>

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

**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

Share this post


Link to post
Share on other sites

Como é que faz para adaptar para um sistema simples de login ?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

Important Information

Ao usar o fórum, você concorda com nossos Terms of Use.