CAPTCHA (“Completely Automated Public Turing test to tell Computers and Humans Apart”) é um teste projetado para ser fácil para humanos e difícil para máquinas. Na prática, é a ferramenta mais comum para reduzir a automação abusiva em formulários: cadastros em massa, credential stuffing, spam de comentários, brute-force de login e abuso de cupons. Mas há muita confusão sobre o que ele garante. Vamos separar o que é mito do que é defesa real.
A tese central deste artigo: CAPTCHA aumenta o custo do ataque automatizado — ele não autentica, não autoriza e não substitui as outras camadas.
Como o CAPTCHA moderno funciona
As soluções atuais quase não mostram “quebra-cabeças” e dependem de sinais de comportamento e reputação do navegador. O fluxo, em qualquer uma delas, é sempre o mesmo:
- O navegador carrega um widget do provedor e coleta sinais (movimento, histórico, reputação de IP, fingerprint).
- O provedor devolve um token opaco para o cliente.
- O formulário envia esse token junto com os demais campos.
- O seu servidor valida o token chamando a API do provedor. Este passo é o que realmente importa.
As opções mais usadas
- reCAPTCHA v2 (“Não sou um robô” / seleção de imagens): desafio visível quando o risco é alto.
- reCAPTCHA v3: invisível, devolve um score de 0.0 a 1.0; você decide o limiar e a ação (bloquear, pedir MFA, exigir um v2).
- hCaptcha: alternativa com foco em privacidade, modelo de desafio semelhante ao v2.
- Cloudflare Turnstile: invisível, sem quebra-cabeças, sem rastreamento cross-site — popular justamente por equilibrar UX e privacidade.
O erro número um: não validar o token no servidor
A falha mais comum que encontramos em pentests é simples e fatal: o site mostra o widget, recebe o token, e nunca o valida no backend — ou valida só no JavaScript do cliente. Como o atacante controla totalmente a requisição que sai do “cliente”, ele simplesmente omite ou falsifica o campo do token e envia o formulário direto para o servidor. O CAPTCHA vira decoração.
A validação correta é server-side, contra a API do provedor:
import requests
def captcha_valido(token, ip_cliente):
r = requests.post(
"https://challenges.cloudflare.com/turnstile/v0/siteverify",
data={
"secret": SECRET_KEY, # segredo do servidor, NUNCA no front
"response": token, # token recebido do formulário
"remoteip": ip_cliente,
},
timeout=5,
)
data = r.json()
return data.get("success") is True
@app.post("/login")
def login():
if not captcha_valido(request.form.get("cf-turnstile-response"), request.remote_addr):
abort(403) # rejeita ANTES de processar o login
# ... segue o fluxo normal
Pontos críticos dessa validação:
- O
secretfica só no servidor. Se vazar para o front, o esquema inteiro cai. - Verifique também os campos que o provedor retorna: hostname (precisa ser o seu domínio),
action(no reCAPTCHA v3) e o timestamp do desafio. - Cada token é de uso único e expira. Rejeite tokens reutilizados e expirados — senão o atacante resolve um desafio uma vez e replica o token mil vezes.
- Para o v3, defina um limiar de score e uma ação para a zona cinzenta (ex.:
score < 0.5→ exigir reCAPTCHA v2 ou MFA, não bloquear de imediato).
Onde encaixar o CAPTCHA — e onde não
Coloque CAPTCHA onde há automação de alto valor:
- Login (especialmente após algumas falhas — CAPTCHA adaptativo).
- Cadastro / criação de conta.
- Reset de senha (também ajuda contra enumeração em massa).
- Formulários públicos de contato/comentário (spam).
- Endpoints caros ou que disparam e-mail/SMS (evita abuso de custo).
Evite CAPTCHA onde ele só atrapalha: em todas as páginas, em cada clique autenticado, ou como única barreira de uma API consumida por outros sistemas (lá, use chaves de API, mTLS e rate limiting).
Os bypasses — por que CAPTCHA sozinho não basta
Nenhum CAPTCHA é inquebrável. Os contornos reais:
- CAPTCHA farms: serviços humanos que resolvem desafios por centavos, via API. Para um atacante motivado, é só um custo operacional.
- Solvers automatizados: modelos de visão e áudio resolvem boa parte dos desafios visuais e sonoros.
- Reuso/replay de token: se o servidor não invalida o token após o uso, um único desafio resolvido vira N requisições.
- Ausência de verificação de hostname: o atacante resolve o CAPTCHA no seu próprio site (com a mesma site key, se exposta) e usa o token no alvo.
- Roubo de token via XSS/man-in-the-middle: se há outra falha na página, o token pode ser capturado.
A lição: o CAPTCHA eleva o custo, mas um adversário determinado paga esse custo. Ele precisa de reforço.
Acessibilidade e UX: o custo do lado humano
CAPTCHAs visuais excluem usuários — pessoas com deficiência visual, daltônicos, quem usa leitor de tela. Boas práticas:
- Prefira soluções invisíveis/adaptativas (Turnstile, reCAPTCHA v3) que só desafiam sob suspeita.
- Sempre ofereça uma alternativa de áudio quando houver desafio visual.
- Garanta navegação por teclado e rótulos ARIA adequados.
- Meça o atrito: CAPTCHA agressivo derruba conversão tanto quanto bots.
CAPTCHA é uma camada — a defesa em profundidade
CAPTCHA deve compor uma estratégia, não ser ela:
- Rate limiting por IP, conta e identificador — a primeira e mais importante barreira contra automação.
- Lockout / backoff progressivo após falhas de login.
- MFA — anula o valor de credenciais roubadas, mesmo que o bot passe.
- Detecção de credential stuffing (senhas vazadas conhecidas, reputação de IP/ASN).
- WAF / bot management para padrões de tráfego anômalos.
- Verificação por e-mail/telefone em fluxos sensíveis.
Pensar nessas camadas em conjunto é o que separa “tem um CAPTCHA” de “resiste a automação”.
Como testamos a proteção de formulários
- Submeter o formulário sem o token e com token inválido/vazio — o servidor rejeita?
- Reutilizar um token válido em várias requisições — ele é invalidado após o primeiro uso?
- Resolver o CAPTCHA em outro domínio e usar o token no alvo — há checagem de hostname?
- Avaliar o rate limiting por trás do CAPTCHA: removido o widget, a automação volta a ser trivial?
- Conferir se o
secretnão vaza no front e se a verificação acontece antes da ação sensível.
Checklist de mitigação
- Validar o token no servidor, contra a API do provedor, antes de processar a ação.
-
secretapenas no backend; nunca confiar em verificação client-side. - Conferir
success, hostname,action/score e expiração do token. - Token de uso único — rejeitar replay.
- CAPTCHA adaptativo nos pontos de alto valor, não em tudo.
- Combinar com rate limiting, lockout, MFA e detecção de credential stuffing.
- Garantir acessibilidade (alternativa de áudio, teclado, ARIA).
CAPTCHA é uma boa ferramenta mal compreendida. Ele não diz que do outro lado há um humano de confiança — diz, no máximo, que automatizar ficou mais caro. Tratado como uma camada de uma defesa em profundidade, ele cumpre bem seu papel. Tratado como a defesa inteira, é uma falsa sensação de segurança que um pentest derruba em minutos.