Desenvolvimento de software

Ataques de tempo em PHP: Um exemplo prático - por que `hash_equals()` é importante

Você gostaria de ter um exemplo realista de um ataque de tempo aos tokens de API no Wordpress/Laravel/PHP? Abordamos esse assunto aqui, incluindo dicas e medidas de práticas recomendadas contra ataques de tempo.

Muitos desenvolvedores confiam na comparação simples usando === ou == ao verificar chaves de API, tokens ou outras cadeias de caracteres secretas. À primeira vista, isso parece razoável, mas há um problema: diferenças de tempo na comparação podem ser exploradas por invasores.

Este artigo descreve um exemplo realista de como um ataque de tempo funciona conceitualmente.

O cenário real (exemplo simplificado)

Imagine que um microsserviço interno aceita solicitações com um token de parâmetro de consulta e o compara com um token de API do GitHub armazenado no ambiente.

Código inseguro (simplificado):

// insecure.php (exemplo simplificado)$expected = getenv('GITHUB_API_TOKEN');// por exemplo, 'V1cHt2S67DADJIm9sX9yzCc272EkSC'$provided = $_GET['token'] ?? '';se ($provided === $expected) { // conceder acesso} PHP  

Explicarei por que isso é problemático na próxima seção.

Como funciona um ataque de tempo?

Se a implementação da comparação de tokens compara caractere por caractere e aborta imediatamente no primeiro erro, então uma solicitação com o primeiro caractere correto demora um pouco mais, em média.

Portanto, um primeiro caractere correto leva, em média, a um tempo de processamento um pouco mais longo do que um primeiro caractere incorreto. O mesmo se aplica ao segundo caractere e assim por diante.

Um invasor tira proveito disso testando todos os caracteres possíveis para cada posição, medindo os tempos de resposta com muita frequência e analisando-os estatisticamente. O caractere com o maior tempo médio/proporcionalmente mais longo provavelmente está correto. Dessa forma, o token é reconstruído passo a passo.

Por que hash_equals() é a escolha certa

O PHP fornece uma função de comparação de strings em tempo constante com hash_equals(). Ela garante que o tempo de execução da comparação não dependa de prefixos comuns, desde que as duas cadeias de caracteres tenham o mesmo comprimento.

Alternativa segura (para Laravel, PHP, Wordpress):

// secure.php$expected = getenv('GITHUB_API_TOKEN'); $provided = $_GET['token'] ?? '';se (hash_equals($expected, $provided)) { // conceder acesso} PHP  

Observação: hash_equals() só é "independente do tempo" se os comprimentos forem iguais. É uma boa prática projetar tokens de modo que o comprimento seja constante (por exemplo, HMACs, UUIDs de comprimento fixo ou cadeias de caracteres Base64 aleatórias de comprimento fixo).

Você sabia? Somente o UUID-V4 é gerado de forma totalmente aleatória e, portanto, é usado com frequência para tokens de segurança. Como não contém informações relacionadas a tempo ou dispositivo, ele oferece um alto nível de imprevisibilidade e, portanto, protege contra ataques baseados em padrões ou previsões. É exatamente por isso que o UUID-V4 é a escolha preferida quando se trata de identificadores seguros e difíceis de adivinhar.

Medidas de defesa adicionais - mais do que apenas hash_equals()

  1. Comprimento constante do token
    Use tokens com um comprimento fixo, por exemplo, UUID-V4. Se um invasor adivinhar o comprimento, isso será menos útil, desde que os caracteres em si sejam seguros.
  2. Limitação de taxa
    Limite as solicitações por IP ou por conta. Os ataques de tempo exigem muitas medições; a limitação da taxa aumenta significativamente o esforço e os custos para o invasor.
  3. Registro e monitoramento
    Reconheça padrões incomuns (muitas tentativas de token, variação sistemática de determinados parâmetros) e reaja automaticamente.
  4. Sal / HMAC / Assinaturas
    Use tokens assinados (HMAC com chave secreta) ou tokens OAuth em vez de comparar abertamente chaves estáticas brutas.
  5. TLS/HTTPS
    A criptografia protege os canais de comunicação - embora não impeça ataques de tempo aos componentes internos do servidor, é um requisito básico.
  6. Rotação de tokens
    A vida útil curta dos tokens reduz o benefício de um token comprometido.

Conclusão

Os ataques de tempo não são um problema puramente teórico - eles foram investigados na prática e podem ter consequências graves, especialmente para pontos de extremidade acessíveis ao público. A boa notícia: para os desenvolvedores de PHP/Laravel/Wordpress, a primeira contramedida é muito simples:

  • Substitua as comparações diretas de strings confidenciais por hash_equals().
  • Garanta comprimentos constantes de tokens, limitação de taxa, registro e gerenciamento seguro de tokens.
Sobre o autor
Fundador e Diretor Executivo da Langmeier Software
Não quero complicar nada. Não quero desenvolver o melhor software empresarial. Não quero ser incluído numa lista de tecnologia de ponta. Porque não é disso que se tratam as aplicações de negócios. Trata-se de garantir que os teus dados estão perfeitamente protegidos. E trata-se de garantir que tudo funciona sem problemas enquanto mantém o controlo total e se pode concentrar no crescimento do seu negócio. A simplicidade e a fiabilidade são os meus princípios orientadores e inspiram-me todos os dias.
 
Procura mais:
PHP, Segurança do disco rígido, Cibersegurança
Artigos relevantes