Timing attacks: ataques baseados em tempo de resposta
1. Introdução aos Timing Attacks
Timing attacks (ataques de temporização) são uma classe de ataques de canal lateral que exploram variações mensuráveis no tempo de processamento de um sistema para extrair informações sensíveis. O princípio fundamental é simples: operações diferentes levam tempos diferentes para serem executadas, e essas diferenças — mesmo que microscópicas — podem revelar segredos como senhas, chaves criptográficas ou tokens de autenticação.
O conceito foi formalizado por Paul Kocher em 1996, que demonstrou como era possível recuperar chaves secretas de algoritmos criptográficos (como RSA e Diffie-Hellman) medindo o tempo de operações de exponenciação modular. Desde então, o ataque evoluiu para aplicações web modernas, onde variações de milissegundos em respostas HTTP podem expor vulnerabilidades críticas.
Os canais laterais temporais se manifestam em diversas camadas: rede (latência de pacotes), CPU (diferenças em ciclos de instrução), cache (tempo de acesso à memória), disco (operações de I/O) e banco de dados (tempo de execução de queries). Para o desenvolvedor web, os vetores mais relevantes são CPU e banco de dados, pois estão sob controle direto do código da aplicação.
2. Como Funcionam os Timing Attacks em Aplicações Web
O cenário clássico envolve a comparação de strings. Considere este código vulnerável em Node.js:
function checkPassword(input, stored) {
if (input.length !== stored.length) return false;
for (let i = 0; i < input.length; i++) {
if (input[i] !== stored[i]) return false;
}
return true;
}
Aqui, o tempo de execução varia conforme a posição do primeiro caractere incorreto. Se a senha correta for "segredo", uma tentativa "segredo" retorna mais rápido que "segredo", pois a falha ocorre apenas no último caractere. Um atacante pode medir esses tempos e deduzir caractere por caractere.
Comparações usando == ou === em linguagens de alto nível também são vulneráveis, pois implementam short-circuit evaluation — param assim que encontram uma diferença. A solução segura é usar funções de comparação em tempo constante, como crypto.timingSafeEqual (Node.js) ou hmac.compare_digest (Python).
Outro vetor comum é a enumeração de usuários. Se um endpoint de login responde mais rápido para usuários inexistentes (porque não precisa verificar senha) do que para existentes (onde a verificação ocorre), o atacante pode mapear usuários válidos:
// Endpoint vulnerável
app.post('/login', (req, res) => {
const user = db.findUser(req.body.username);
if (!user) {
return res.status(401).send('Credenciais inválidas');
}
// Só chega aqui se usuário existe → tempo maior
if (!checkPassword(req.body.password, user.password)) {
return res.status(401).send('Credenciais inválidas');
}
// Sucesso
});
3. Cenários Práticos de Exploração
Autenticação: O ataque incremental de senhas é o mais conhecido. Com medições precisas, um atacante pode descobrir uma senha de 8 caracteres em cerca de 8×N tentativas (onde N é o tamanho do alfabeto), em vez de N^8 tentativas de força bruta.
APIs REST: Endpoints que filtram dados condicionalmente podem vazar informações. Por exemplo, um endpoint /api/users/:id que retorna 404 mais rápido para IDs inexistentes do que para existentes (que precisam buscar no banco e montar a resposta).
Bancos de dados: Ataques de injeção temporal usam funções como SLEEP() (MySQL) ou BENCHMARK() (MySQL) para introduzir atrasos controlados:
' OR IF(SUBSTRING(password,1,1)='a', SLEEP(2), 0) --
Se a resposta demorar 2 segundos, o atacante sabe que o primeiro caractere da senha é 'a'. Essa técnica permite extrair dados completos do banco mesmo quando a aplicação não exibe resultados diretamente.
4. Técnicas de Medição e Precisão
Para explorar timing attacks com sucesso, o atacante precisa de medições precisas. O ruído de rede e a variação de carga do servidor são os principais obstáculos. As técnicas incluem:
- Múltiplas amostras: Realizar dezenas ou centenas de requisições para o mesmo input e usar a mediana (mais robusta que a média contra outliers).
- Requisições locais: Quando possível, executar o ataque na mesma rede (ou máquina) para reduzir latência de rede.
- Ferramentas:
timedo Linux para medições básicas, bibliotecas Python comotimeiterequestspara scripts automatizados, e ferramentas comowrkpara carga controlada.
Exemplo de script de medição em Python:
import requests
import time
import statistics
def measure_time(url, payload):
times = []
for _ in range(100):
start = time.perf_counter()
requests.post(url, json=payload)
end = time.perf_counter()
times.append(end - start)
return statistics.median(times)
5. Mitigações Essenciais para Desenvolvedores
1. Funções de comparação em tempo constante: Sempre use funções específicas:
- Node.js:
crypto.timingSafeEqual(a, b) - Python:
hmac.compare_digest(a, b) - Java:
MessageDigest.isEqual(a, b) - PHP:
hash_equals(a, b)
2. Aleatorização de respostas: Adicione atrasos artificiais ou ruído controlado para mascarar diferenças temporais. Exemplo:
function loginResponse() {
// Atraso artificial para normalizar tempos
const delay = Math.random() * 50 + 50; // 50-100ms
setTimeout(() => {
res.status(401).send('Credenciais inválidas');
}, delay);
}
3. Normalização de erros: Mensagens de erro genéricas sem distinção entre "usuário não encontrado" e "senha incorreta". Nunca retorne informações que indiquem qual parte da validação falhou.
4. Rate limiting: Limite tentativas por IP, sessão ou conta de usuário. Isso não elimina o timing attack, mas reduz drasticamente a janela de exploração.
6. Ferramentas e Frameworks de Proteção
- Helmet.js (Node.js): Middleware que define headers de segurança, incluindo proteções contra timing attacks em comparações de strings.
- Django Security Middleware: Inclui proteções contra enumeração de usuários e normalização de mensagens de erro.
- OWASP ESAPI: Biblioteca de segurança com funções de comparação em tempo constante.
- Rate limiting libraries:
express-rate-limit(Node.js),django-ratelimit(Python),rack-attack(Ruby). - Ferramentas de monitoramento: New Relic, Datadog ou ELK Stack para detectar padrões anômalos de tempo de resposta que indicam tentativas de ataque.
7. Casos Reais e Lições Aprendidas
CVE-2009-1431: Vulnerabilidade no HMAC do Ruby on Rails. A implementação original usava comparação caractere por caractere, permitindo que atacantes descobrissem tokens de autenticação medindo tempos de resposta. A correção introduziu secure_compare com tempo constante.
Caso GitHub (2014): Pesquisadores descobriram que a API do GitHub vazava informações sobre a existência de repositórios privados através de diferenças de tempo de resposta entre endpoints autorizados e não autorizados. O GitHub corrigiu adicionando delays artificiais.
Lições para desenvolvedores:
- Nunca confie em tempos de resposta como fonte de segurança.
- Assuma que qualquer diferença temporal pode ser explorada.
- Trate timing attacks como vulnerabilidades de primeira classe, não como "ruído teórico".
8. Conclusão e Próximos Passos
Timing attacks são uma ameaça real e subestimada no desenvolvimento web. Eles exploram o fato de que "tempo é informação" — cada milissegundo de diferença pode vazar um bit de dado sensível.
Checklist para código seguro:
- [ ] Todas as comparações de strings sensíveis usam funções de tempo constante
- [ ] Mensagens de erro são genéricas e não revelam qual validação falhou
- [ ] Endpoints de autenticação têm delays normalizados
- [ ] Rate limiting está implementado
- [ ] Testes automatizados verificam tempos de resposta para entradas válidas e inválidas
Próximos passos: Integre testes de regressão de tempo em seu pipeline de CI/CD. Ferramentas como timing-attack-tester (npm) podem automatizar a detecção de vulnerabilidades temporais. Estude também temas vizinhos como side-channel attacks em cache e ataques de temporização em WebSockets.
A segurança contra timing attacks não é opcional — é uma responsabilidade fundamental de todo desenvolvedor que lida com dados sensíveis.
Referências
- OWASP Timing Attack — Artigo completo da OWASP sobre timing attacks, incluindo exemplos de código e mitigações
- Node.js Crypto Documentation - timingSafeEqual — Documentação oficial da função de comparação em tempo constante do Node.js
- Python HMAC Documentation - compare_digest — Documentação oficial da função segura de comparação de digests em Python
- CVE-2009-1431 - Ruby on Rails HMAC Timing Attack — Detalhes da vulnerabilidade clássica de timing attack no framework Ruby on Rails
- Timing Attacks on Web Applications (MITRE) — Entrada do Common Weakness Enumeration sobre timing attacks, com classificações e exemplos
- GitHub Security Lab - Timing Attack Research — Pesquisas e artigos do GitHub Security Lab sobre timing attacks em APIs REST