Objetivos de aprendizado
Depois de ler este artigo, você vai conseguir:
- Entender como funciona um ataque de força bruta e suas variações
- Diferenciar ataques online, offline, password spraying e credential stuffing
- Proteger um login e um servidor SSH com limite de tentativas, hash e MFA
Basta colocar um formulário de login ou um servidor SSH na internet para os logs mostrarem tentativas de acesso que você não fez. Quase sempre são robôs testando combinações de usuário e senha, sem pressa e sem parar. É o ataque mais antigo e simples que existe, e continua funcionando porque muita porta ainda fica destrancada.
Saber como ele funciona mostra onde colocar cada defesa: por que algumas variantes acertam em segundos e outras nunca terminam, e o que você pode aplicar hoje no seu login e no seu SSH.
O que é um ataque de força bruta?#
É a tentativa de descobrir um segredo (senha, PIN, chave de API, token) testando possibilidades em massa até uma funcionar. Não explora falha no código: explora o fato de que o segredo pode ser adivinhado em tempo viável.
O MITRE ATT&CK, catálogo de técnicas de ataque usado por equipes de segurança no mundo todo, registra a força bruta como a técnica T1110, usada para acessar contas quando a senha é desconhecida ou quando o atacante já tem os hashes. Ela tem quatro subtécnicas:
- Adivinhação de senha (T1110.001): muitas senhas contra uma conta, geralmente a partir de listas de senhas comuns.
- Quebra de senha (T1110.002): o atacante já tem os hashes, por exemplo de um banco vazado, e testa senhas no próprio computador.
- Password spraying (T1110.003): poucas senhas muito comuns contra muitas contas, para não disparar bloqueio por conta.
- Credential stuffing (T1110.004): pares de e-mail e senha vazados de outro site, testados no seu. Funciona porque muita gente repete a senha.
Como o ataque funciona na prática?#
Um ataque online mira o seu sistema no ar: o robô envia uma requisição de login por tentativa e lê a resposta. Cada tentativa custa uma ida e volta na rede, e você pode contá-las e barrá-las.
Um ataque offline acontece depois de um vazamento. Com os hashes em mãos, o atacante testa senhas na própria máquina, sem limite de tentativas e sem que você veja. Aí a única barreira é o algoritmo de hash: quanto mais lento e caro em memória, menos senhas por segundo o atacante consegue testar.
A conta do espaço de busca mostra por que o comprimento importa. Uma senha de 8 letras minúsculas tem 26^8, cerca de 209 bilhões de combinações. Uma de 15 caracteres com o mesmo alfabeto tem 26^15, cerca de 1,7 x 10^21. Cada caractere a mais multiplica o trabalho por 26. Só que atacantes raramente testam tudo: começam por listas de senhas vazadas, então uma senha longa e já vazada cai em segundos.
Onde os ataques de força bruta acontecem?#
- Formulários de login de sites, painéis e APIs.
- SSH, RDP e FTP expostos na internet com autenticação por senha.
- Painéis administrativos com endereço conhecido, como
/wp-adminou/admin. - Endpoints de redefinição de senha e verificação de códigos de 6 dígitos, que têm só 1 milhão de combinações.
- Chaves e tokens curtos ou previsíveis. Uma chave de API longa e aleatória não se adivinha; uma que vazou no GitHub nem precisa ser adivinhada, como mostra chave de API exposta no GitHub.
Como proteger um formulário de login?#
As defesas funcionam em camadas, e nenhuma resolve sozinha.
- Limite de tentativas por IP e por conta. O OWASP recomenda associar o contador à conta, não só ao IP, porque o atacante troca de endereço. O NIST SP 800-63B-4 exige limitar as falhas consecutivas a no máximo 100 por conta.
- Mensagem genérica. Responda "e-mail ou senha inválidos" nos dois casos. Mensagens diferentes, códigos HTTP diferentes ou tempos de resposta diferentes revelam quais contas existem.
- Hash lento. Guarde senhas com Argon2id. O OWASP recomenda no mínimo 19 MiB de memória, 2 iterações e paralelismo 1; scrypt e bcrypt (fator de custo 10 ou mais) são alternativas.
- Senhas longas, sem regras de composição. O NIST pede no mínimo 15 caracteres para senha usada como único fator (8 com MFA), uma lista de bloqueio de senhas comuns e vazadas, e nada de obrigar troca periódica sem indício de vazamento.
- MFA. É a defesa mais forte: mesmo com a senha certa, o atacante para no segundo fator.
- CAPTCHA depois de algumas falhas. O OWASP o trata como defesa em profundidade, que encarece o ataque, não como barreira definitiva.
Um exemplo em Node.js com Express 5, express-rate-limit 8 e argon2, com limite por IP e por conta:
// npm install express@5 express-rate-limit@8 argon2
import argon2 from "argon2";
import express from "express";
import { rateLimit } from "express-rate-limit";
const app = express();
app.set("trust proxy", 1); // atrás de um proxy reverso, usa o IP real do cliente
app.use(express.json());
const tooMany = { error: "Muitas tentativas. Tente de novo mais tarde." };
// Por IP: até 20 tentativas com falha a cada 15 minutos
const ipLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
limit: 20,
skipSuccessfulRequests: true,
standardHeaders: "draft-8",
legacyHeaders: false,
message: tooMany,
});
// Por conta: até 5 tentativas com falha a cada 15 minutos, venham de onde vierem
const accountLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
limit: 5,
skipSuccessfulRequests: true,
keyGenerator: (req) => String(req.body?.email ?? "").toLowerCase(),
standardHeaders: "draft-8",
legacyHeaders: false,
message: tooMany,
});
// Exemplo: em produção, os hashes vêm do banco de dados
const users = new Map([
["ana@example.com", await argon2.hash("uma frase-senha longa de exemplo")],
]);
// Hash usado quando o e-mail não existe, para o tempo de resposta não denunciar contas
const dummyHash = await argon2.hash("conta-inexistente");
app.post("/login", ipLimiter, accountLimiter, async (req, res) => {
const { email, password } = req.body ?? {};
if (typeof email !== "string" || typeof password !== "string") {
return res.status(400).json({ error: "Requisição inválida" });
}
const hash = users.get(email.toLowerCase());
const valid = await argon2.verify(hash ?? dummyHash, password);
if (!hash || !valid) {
// mesma mensagem para e-mail inexistente e senha errada
return res.status(401).json({ error: "E-mail ou senha inválidos" });
}
res.json({ ok: true });
});
app.listen(Number(process.env.PORT) || 3000);O skipSuccessfulRequests faz só as falhas contarem. Depois de cinco falhas para a mesma conta, a próxima tentativa recebe 429 Too Many Requests até a janela de 15 minutos terminar. O argon2.hash usa Argon2id por padrão, com parâmetros acima do mínimo do OWASP. Num servidor com várias instâncias, troque o armazenamento em memória do limitador por um compartilhado, como Redis.
Como proteger um servidor SSH?#
A defesa mais eficaz é eliminar a senha. Com chave SSH não há o que adivinhar; veja o que são chaves SSH. No /etc/ssh/sshd_config, depois de confirmar que o login por chave funciona:
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin noReinicie o serviço SSH e teste numa segunda sessão antes de fechar a atual. Para cortar o ruído dos robôs, o fail2ban lê os logs e bloqueia IPs com falhas repetidas. Os padrões do jail.conf são 5 falhas (maxretry) em 10 minutos (findtime) para 10 minutos de bloqueio (bantime). Um /etc/fail2ban/jail.local que estende o bloqueio:
[sshd]
enabled = true
maxretry = 5
findtime = 10m
bantime = 1hQuais são os limites dessas defesas?#
Bloqueio por conta tem um efeito colateral: um atacante pode errar a senha de propósito para trancar a conta de outra pessoa. O OWASP sugere bloqueios curtos e crescentes e deixar o fluxo de "esqueci a senha" disponível mesmo durante o bloqueio.
Um limite só por IP não segura ataques distribuídos, e CAPTCHA pode ser resolvido por serviços pagos. Nenhuma dessas defesas ajuda se a senha já vazou e o usuário a repete em outros sites; contra isso, só MFA e listas de bloqueio de senhas vazadas.
Força bruta também não é a mesma coisa que DDoS. Os dois geram muitas requisições, mas o DDoS quer derrubar o serviço, e a força bruta quer entrar nele. Um WAF pode ajudar a filtrar tráfego automatizado, mas quantas tentativas de login cada conta aceita é uma regra do seu código. Para o restante da proteção, use o checklist de segurança para deploy.
Como fazer isso na Square Cloud#
Na Square Cloud, a parte do SSH fica de fora: a aplicação só recebe tráfego de entrada na porta 80, publicada por HTTPS, então não existe um servidor SSH seu exposto para os robôs testarem senhas. O que sobra é o formulário de login, e ali as camadas se dividem. A rede na frente das aplicações tem WAF e mitigação de DDoS nas camadas L3, L4 e L7 em todos os planos, o que filtra tráfego de rede; limite de tentativas, hash lento e MFA continuam no seu código, como no exemplo acima.
Se você servir o mesmo domínio com load balancing (a partir do Standard), cada aplicação teria o próprio contador em memória, e o atacante ganharia tentativas extras a cada instância. Como não há sticky session, troque o armazenamento do express-rate-limit por um compartilhado: a hospedagem de Redis, também a partir do Standard, fica no mesmo datacenter das aplicações. Guarde a URL do Redis e os segredos de sessão em variáveis de ambiente da aplicação, nunca no código; a mudança vale no próximo restart.
Para enxergar o ataque, o analytics web incluído em todo plano mostra rotas e status codes: um salto de respostas 401 e 429 é o sinal. Veja a proteção na página de rede, configure os segredos em variáveis de ambiente e conheça a hospedagem de Redis.
Infraestrutura
Mitigação de DDoS L3/L4/L7 e WAF em todos os planos
Perguntas frequentes
Quanto tempo leva um ataque de força bruta?
Depende do tamanho do espaço de senhas e da velocidade de teste. Online, com limite de tentativas, uma senha longa e fora de listas vazadas fica fora de alcance. Offline, contra um banco de hashes vazado, o hash lento (Argon2id, scrypt, bcrypt) é o que segura o atacante.
Força bruta é crime?
Tentar acessar sistema ou conta alheia sem autorização é crime em muitos países. No Brasil, a Lei 12.737/2012 tipifica a invasão de dispositivo informático. Teste só sistemas seus ou com autorização por escrito.
Bloquear o IP depois de algumas falhas resolve?
Ajuda, mas não basta. Ataques distribuídos usam milhares de IPs, então o OWASP recomenda contar as falhas também por conta. O cuidado é não permitir que um atacante bloqueie contas legítimas de propósito.
Qual a defesa mais eficaz contra força bruta?
Autenticação multifator (MFA). O OWASP cita uma análise da Microsoft segundo a qual o MFA teria impedido 99,9% dos comprometimentos de conta. Combine com limite de tentativas e senhas longas.
Mais em Segurança
Ver todos os 10 artigos- Checklist de segurança para quem publica bot, site ou APIChecklist de segurança antes de publicar bot, site ou API: segredos em variáveis de ambiente, dependências, HTTPS, cabeçalhos, permissões mínimas e logs.
- Como proteger seu site ou bot contra DDoSPara se proteger de DDoS, combine mitigação na borda (CDN e WAF) com limite de requisições, timeouts e cache na aplicação. Veja o passo a passo com código.
- Chave de API exposta no GitHub: como revogar e prevenirSubiu uma chave de API para o GitHub? Revogue primeiro, depois limpe o histórico e troque o valor. Veja o passo a passo e como evitar que se repita.
- Vazou o token do bot? O que fazer agoraSe o token do bot vazou, redefina-o no Portal do Discord (ou com /token no BotFather) antes de qualquer outra coisa. Veja a ordem certa e como checar o estrago.