Tempo de verificação até o tempo de uso - Time-of-check to time-of-use

No desenvolvimento de software , o tempo de verificação até o tempo de uso ( TOCTOU , TOCTTOU ou TOC / TOU ) é uma classe de bugs de software causados ​​por uma condição de corrida envolvendo a verificação do estado de uma parte de um sistema (como uma credencial de segurança) e o uso dos resultados dessa verificação.

As condições de corrida TOCTOU são comuns no Unix entre as operações no sistema de arquivos , mas podem ocorrer em outros contextos, incluindo soquetes locais e uso impróprio de transações de banco de dados . No início da década de 1990, o utilitário de e-mail do BSD 4.3 UNIX tinha uma condição de corrida explorável para arquivos temporários porque usava a mktemp()função. As primeiras versões do OpenSSH tinham uma condição de corrida explorável para sockets de domínio Unix . Eles continuam sendo um problema nos sistemas modernos; a partir de 2019, uma condição de corrida TOCTOU no Docker permite acesso root ao sistema de arquivos da plataforma host.

Exemplos

No Unix , o seguinte código C , quando usado em um setuidprograma, tem um bug TOCTOU:

if (access("file", W_OK) != 0) {
    exit(1);
}

fd = open("file", O_WRONLY);
write(fd, buffer, sizeof(buffer));

Aqui, o acesso destina-se a verificar se o usuário real que executou o setuidprograma normalmente teria permissão para gravar o arquivo (ou seja, accessverifica o ID do usuário real em vez do ID do usuário efetivo ).

Esta condição de corrida é vulnerável a um ataque:

Vítima Atacante
if (access("file", W_OK) != 0) {
    exit(1);
}

fd = open("file", O_WRONLY);
// Actually writing over /etc/passwd
write(fd, buffer, sizeof(buffer));
// 
//
// After the access check
symlink("/etc/passwd", "file");
// Before the open, "file" points to the password database
//
//

Neste exemplo, um invasor pode explorar a condição de corrida entre o accesse openpara enganar a setuidvítima e fazê-la sobrescrever uma entrada no banco de dados de senhas do sistema. As corridas TOCTOU podem ser usadas para escalonamento de privilégios , para obter acesso administrativo a uma máquina.

Embora essa sequência de eventos exija um tempo preciso, é possível para um invasor organizar essas condições sem muita dificuldade.

A implicação é que os aplicativos não podem assumir que o estado gerenciado pelo sistema operacional (neste caso, o namespace do sistema de arquivos) não mudará entre as chamadas do sistema.

Cronometragem confiável de TOCTOU

Explorar uma condição de corrida TOCTOU requer um tempo preciso para garantir que as operações do invasor se intercalem adequadamente com as da vítima. No exemplo acima, o invasor deve executar a symlinkchamada do sistema precisamente entre accesse open. Para o ataque mais geral, o atacante deve ser agendado para execução após cada operação da vítima, também conhecido como "passo único" da vítima.

No caso do utilitário de correio BSD 4.3 e mktemp (), o invasor pode simplesmente continuar executando o utilitário de correio em um processo, adivinhar os nomes dos arquivos temporários e continuar criando links simbólicos em outro processo. O ataque geralmente pode ser bem-sucedido em menos de um minuto.

As técnicas para uma única etapa do programa da vítima incluem labirintos do sistema de arquivos e ataques de complexidade algorítmica. Em ambos os casos, o invasor manipula o estado do sistema operacional para controlar o agendamento da vítima.

Os labirintos do sistema de arquivos forçam a vítima a ler uma entrada de diretório que não está no cache do sistema operacional, e o sistema operacional coloca a vítima para dormir enquanto lê o diretório do disco. Ataques de complexidade algorítmica forçam a vítima a gastar todo o seu quantum de agendamento dentro de uma única chamada de sistema, percorrendo a tabela hash do kernel de nomes de arquivos em cache. O invasor cria um grande número de arquivos com nomes que têm o mesmo valor que o arquivo que a vítima pesquisará.

Prevenindo TOCTOU

Apesar da simplicidade conceitual, as condições de corrida TOCTOU são difíceis de evitar e eliminar. Uma técnica geral é usar tratamento de erros em vez de verificação prévia, sob a filosofia de EAFP - "É mais fácil pedir perdão do que permissão" em vez de LBYL - "olhe antes de pular" - neste caso, não há verificação, e a falha de suposições para manter são sinalizados por um erro que está sendo retornado.

No contexto das condições de corrida do sistema de arquivos TOCTOU, o desafio fundamental é garantir que o sistema de arquivos não possa ser alterado entre duas chamadas de sistema. Em 2004, foi publicado um resultado de impossibilidade, mostrando que não havia uma técnica portátil determinística para evitar as condições de corrida de TOCTOU.

A partir dessa impossibilidade, bibliotecas para rastrear descritores de arquivos e garantir a correção têm sido propostas pelos pesquisadores.

Uma solução alternativa proposta na comunidade de pesquisa é que os sistemas UNIX adotem transações no sistema de arquivos ou no kernel do SO. As transações fornecem uma abstração de controle de simultaneidade para o sistema operacional e podem ser usadas para evitar corridas de TOCTOU. Embora nenhum kernel UNIX de produção ainda tenha adotado transações, protótipos de pesquisa de prova de conceito foram desenvolvidos para Linux, incluindo o sistema de arquivos Valor e o kernel TxOS. O Microsoft Windows adicionou transações ao seu sistema de arquivos NTFS , mas a Microsoft desencoraja seu uso e indicou que elas podem ser removidas em uma versão futura do Windows.

O bloqueio de arquivo é uma técnica comum para evitar condições de corrida para um único arquivo, mas não se estende ao namespace do sistema de arquivos e outros metadados, nem o bloqueio funciona bem com sistemas de arquivos em rede e não pode evitar condições de corrida TOCTOU.

Para binários setuid, uma solução possível é usar a seteuid()chamada do sistema para alterar o usuário efetivo e, em seguida, executar o open(). As diferenças setuid()entre os sistemas operacionais podem ser problemáticas.

Veja também

Referências

Leitura adicional