Desafio do dia:
Bloquear tentativas excessivas de post em um formulário sem ser através da programação do sistema, pois persistência das tentativas em banco, por exemplo, seria muito pesado.
Esta dica também é útil para sistemas com código-fonte fechado que rodam em ambiente apache.
Num cenário hipotético, vamos considerar que:
- O processamento do formulário seja enviado via POST para o arquivo /login.php
- O limite de tentativas consecutivas será 5
Para tal, vamos editar o vhost do domínio em questão (ex: /etc/apache2/sites-enabled/000-default) e adicionar as seguintes linhas:
SecAction phase:1,id:109,initcol:ip=%{REMOTE_ADDR},nolog
SecRule REQUEST_FILENAME "/login.php$" "chain,nolog,phase:1,id:110,setvar:ip.ddos_login=+1,deprecatevar:ip.ddos_login=5/10"
SecRule REQUEST_METHOD "POST"
SecRule REQUEST_FILENAME "/login.php$" "chain,id:111,msg:'Possible Brute Force Attack',deny,status:509"
SecRule REQUEST_METHOD "POST" "chain"
SecRule IP:DDOS_LOGIN "@gt 5"
ErrorDocument 509 "Rate Limit Exceeded"
Explicando o funcionamento:
A primeira regra, cria um objeto chamado ip, que será único para cada REMOTE_ADDR (variável de ambiente do apache, que recebe o IP de conexão).
O bloco de regras a seguir, é uma chain do modsecurity, que, para cada POST no /login.php, incrementa um contador interno chamado ip.ddos_login
O terceiro bloco de regras é uma segunda chain que, quando o contador ip.ddos_login for maior do que 5, e a requisição for um POST em login.php, ira forçar o apache a devolver o http status 509 (Rate Limit Exceeded)
A última linha, serve somente para que seja exibido uma mensagem fixa quando browser do usuário recebe o status http 509, pode ser também o path para um arquivo html.