Se você tem um sistema onde os usuários podem se inscrever e escolher suas próprias senhas, provavelmente você é um alvo para ataques de força bruta, como um ataque de dicionário . Você pode limitar esse problema mostrando ao usuário o quão forte é sua senha. No entanto, forçar os usuários a inserir uma senha realmente forte irá irritá-los, pois eles gostam de algo que possam lembrar.
Outra forma que você pode colocar é bloquear um endereço IP por alguns minutos após uma série de falhas de login. Esta não é uma proteção à prova d’água, mas o hacker agora requer um botnet para realizar o ataque de força bruta. Este é um obstáculo que deve manter os hackers casuais e os script kiddies de fora. Portanto, com base nos dados que você está protegendo, essa deve ser uma defesa decente.
Configurar essa defesa não é difícil. Vou mostrar um exemplo de como fazer isso com o cache do usuário APC .
<?php
$apc_key = "{$_SERVER['SERVER_NAME']}~login:{$_SERVER['REMOTE_ADDR']}";
$tries = (int)apc_fetch($apc_key);
if ($tries >= 10) {
header("HTTP/1.1 429 Too Many Requests");
echo "You've exceeded the number of login attempts. We've blocked IP address {$_SERVER['REMOTE_ADDR']} for a few minutes.";
exit();
}
$success = login($_POST['username'], $_POST['password']);
if (!$success) {
apcu_inc($apc_key, $tries+1, 600); # store tries for 10 minutes
} else {
apc_delete($apc_key);
}
Aumentando o tempo de bloqueio
O bloqueio de um IP pode afetar todo o escritório, o que pode ser irritante. Começar com um tempo limite baixo e aumentá-lo cada vez que um IP é bloqueado ajudará contra isso.
<?php
$apc_key = "{$_SERVER['SERVER_NAME']}~login:{$_SERVER['REMOTE_ADDR']}";
$apc_blocked_key = "{$_SERVER['SERVER_NAME']}~login-blocked:{$_SERVER['REMOTE_ADDR']}";
$tries = (int)apc_fetch($apc_key);
if ($tries >= 10) {
header("HTTP/1.1 429 Too Many Requests");
echo "You've exceeded the number of login attempts. We've blocked IP address {$_SERVER['REMOTE_ADDR']} for a few minutes.";
exit();
}
$success = login($_POST['username'], $_POST['password']);
if (!$success) {
$blocked = (int)apc_fetch($apc_blocked_key);
apc_store($apc_key, $tries+1, pow(2, $blocked+1)*60); # store tries for 2^(x+1) minutes: 2, 4, 8, 16, ...
apc_store($apc_blocked_key, $blocked+1, 86400); # store number of times blocked for 24 hours
} else {
apc_delete($apc_key);
apc_delete($apc_blocked_key);
}