Proteja-se contra brute-forces

Um tipo de ataque que pode causar uma paragem bruta do PHP (e um possível DDoS) é uma “chuva” de submits, talvez uma tentativa de brute-force onde um (ou mais) formulário é preenchido e enviado várias vezes consecutivas na tentativa de derrubar o servidor ou só descobrir uma senha.

Isso acontece, dependendo do servidor e das configurações do mesmo, o PHP não vai conseguir dar conta de tantas requisições, vai ficar perdido e vai parar… Há possibilidade de evitar este tipo de “ataque” fazendo alguns ajustes no servidor e instalando alguns mods do Apache… Mas há também como proteger em-se disso directamente no PHP, e é disso que vou falar hoje.

Antes de tudo vamos falar de algo óbvio, mas que pouca gente deve ter percebido: a variável global $_POST existe sempre… Independente se houve ou não um submit antes. Quando estão a navegar pelo site o $_POST (que é um array) vai ser sempre vazio, sem elementos, e quando houverem dados para o PHP processar (depois de um submit) vai passar a ser um array com elementos.

Então, no começo do nosso script, precisamos verificar se há algum valor dentro de $_POST, se ele não está vazio:

// Verifica se $_POST não está vazio
if (!empty($_POST)) {
// :]
}

?>


Agora que já sabemos quando houve um submit, vamos verificar se existe um valor salvo na sessão que nos informará a hora exacta do último submit aceite pelo sistema (em UNIX TIMESTAMP)… Por questão de optimização de código também vamos colocar, directo no mesmo IF, uma verificação que compara esse horário procurando na sessão (caso ele exista) com o horário actual… Vamos directo ao script para ser mais fácil de entender:

// Verifica se $_POST não está vazio
if (!empty($_POST)) {
$segundos = 10; // Tempo mínimo entre dois submits (em segundos)
$agora = time(); // "Agora" em UNIXTIMESTAMP

// Verifica se a variável da sessão existe E verifica a diferença de tempo
if (isset($_SESSION['ultimoSubmit']) AND ($_SESSION['ultimoSubmit'] > ($agora - $segundos))) {
// O submit será bloqueado
}
}

?>
 
Viram? Caso o IF seja verdadeiro vamos bloquear o submit com um echo e um exit (podem ainda redirecionar o visitante para outro local, ou fazer da forma como preferirem)… E caso o IF seja falso o script continuará normalmente…

// Verifica se $_POST não está vazio
if (!empty($_POST)) {
$segundos = 10; // Tempo mínimo entre dois submits (em segundos)
$agora = time(); // "Agora" em UNIXTIMESTAMP

// Verifica se a variável da sessão existe E verifica a diferença de tempo
if (isset($_SESSION['ultimoSubmit']) AND ($_SESSION['ultimoSubmit'] > ($agora - $segundos))) {
// O submit será bloqueado
echo "Aguarde mais de {$segundos} segundos para enviar o formulário!";
exit;
}
// Salva a hora do último submit
$_SESSION['ultimoSubmit'] = $agora;
}

?>
 
Prestem atenção nas linhas marcadas…
Nas linhas 11 e 12 será onde ocorre o bloqueio em si e na linha 15 onde salvamos o horário do último submit caso ele seja aceite.

Caso pretenderem bloquear todas as tentativas de submit que não tenham $segundos entre si, necessitam de salvar o horário do ultimo submit mesmo quando bloquear a tentativa, da seguinte forma:
 
// Verifica se a variável da sessão existe E verifica a diferença de tempo
if (isset($_SESSION['ultimoSubmit']) AND ($_SESSION['ultimoSubmit'] > ($agora - $segundos))) {
// O submit será bloqueado
$_SESSION['ultimoSubmit'] = $agora;
echo "Aguarde mais de {$segundos} segundos para enviar o formulário!";
exit;
}
 
Atenção: Esse script não vos protege totalmente contra ataques brute-force ou DDoS, apenas AJUDA a
evitar que isso aconteça.

Cumprimentos
Pirata Da Fajã

Sem comentários: