Race Condition é uma classe de vulnerabilidades frequentemente subestimada em aplicações web. Ela ocorre quando um servidor processa múltiplas requisições simultaneamente sem a devida sincronização. Quando duas ou mais requisições chegam ao servidor no mesmo instante e afetam os mesmos dados, uma colisão pode acontecer. Os resultados dessas colisões variam de bugs triviais a falhas críticas que permitem contornar verificações de segurança, realizar cobranças duplicadas, obter acesso a contas de terceiros ou exceder limites estabelecidos.
Para entender melhor como essas vulnerabilidades operam em aplicações web reais e onde procurar por pontos fracos, é crucial analisar os diferentes tipos de Race Condition. Podemos categorizá-las em três tipos principais:
-
Limit Overrun (TOCTOU - Time of Check, Time of Use): Este é o tipo mais comum. A vulnerabilidade reside na capacidade de um atacante contornar uma limitação imposta pela lógica de negócios da aplicação. Isso é feito enviando múltiplas requisições em paralelo no exato momento em que o servidor ainda não atualizou o estado após o processamento da primeira requisição. A lógica típica envolve uma verificação (por exemplo, saldo suficiente, cupom não utilizado) seguida por uma ação (débito, aplicação de desconto). Existe uma pequena janela de tempo entre essas duas etapas (a "race window"). Se múltiplas requisições forem enviadas durante essa janela, todas passarão pela verificação e executarão a ação, pois nenhuma delas terá tido tempo de atualizar o estado. Este tipo é encontrado em cenários com limites ou operações únicas, como aplicação de cupons promocionais, débito de bônus, saques, ativação de assinaturas, convites para equipes, votações e avaliações.
- Exemplo prático: Um atacante pode explorar essa falha em sistemas de bônus, enviando várias requisições paralelas para usar os mesmos bônus em múltiplas compras, mesmo que os bônus fossem destinados a uma única transação. Da mesma forma, em sistemas de cashback, é possível acumular múltiplos cashbacks limitados enviando requisições em paralelo.
-
Single-endpoint Collision: Diferente do Limit Overrun, que foca em contornar limites, o Single-endpoint Collision envolve uma colisão de dados. Ocorre quando duas requisições modificam o mesmo campo simultaneamente, e a segunda requisição sobrescreve os dados da primeira antes que esta possa utilizá-los. Isso resulta na aplicação operando com dados incorretos. Esse tipo é comum em funcionalidades como troca de e-mail com confirmação por token, troca de número de telefone com verificação por SMS ou redefinição de senha onde o token de reset é armazenado na sessão. Um exemplo notório foi uma vulnerabilidade no GitLab (CVE-2022-4037), onde um atacante podia vincular o e-mail de outra pessoa à sua conta. A lógica normal envolvia enviar uma requisição para mudar o e-mail, o servidor gravava o novo e-mail como
pending_email, gerava um token de confirmação e enviava um e-mail para o novo endereço. No entanto, se dois atacantes enviassem requisições de mudança de e-mail em paralelo, o campopending_emailpoderia ser sobrescrito. O primeiro fluxo geraria um token para um e-mail, mas o segundo fluxo sobrescreveria opending_emailcom outro. O servidor, então, enviaria o e-mail de confirmação para o endereço do atacante, mas o token estaria associado ao e-mail da vítima, permitindo o sequestro da conta. -
Multi-endpoint Race: Este tipo envolve a exploração de uma falha entre múltiplos endpoints que fazem parte de um processo de várias etapas. A vulnerabilidade ocorre no intervalo entre a execução de uma ação e a conclusão de outra. Por exemplo, em um processo de login com OTP (One-Time Password), o fluxo pode envolver: inicializar o processo, enviar o código OTP e verificar o código. Se um atacante puder enviar uma requisição para alterar o e-mail associado ao fluxo de autenticação e, em seguida, enviar uma requisição para verificar o OTP (que foi enviado para o e-mail original do atacante), ele pode obter acesso à conta da vítima. A chave aqui é que dois endpoints (por exemplo, um para iniciar a autenticação e outro para verificar o código) operam sobre a mesma entidade (o fluxo de autenticação) e podem ser chamados em paralelo, mesmo que a lógica da aplicação sugira uma execução sequencial. Um exemplo prático seria em plataformas de e-commerce onde a autorização é feita via código de e-mail. Um atacante pode iniciar o processo de login com seu próprio e-mail, receber o OTP, e então, em paralelo, enviar uma requisição para alterar o e-mail associado ao fluxo para o e-mail da vítima. Em seguida, ele usa o OTP que recebeu para fazer login, mas a sessão é criada para o e-mail da vítima, resultando em um Account Takeover.
Ferramentas e Proteção: Ferramentas como o Burp Suite, através do seu módulo Repeater, permitem duplicar requisições e enviá-las em paralelo. Extensões como o Turbo Intruder oferecem scripts mais avançados para explorar essas vulnerabilidades. Para se proteger, as empresas devem implementar operações atômicas (combinando verificação e ação em uma única unidade), bloqueio de linhas no banco de dados, chaves de idempotência, bloqueios distribuídos e filas para processamento de operações críticas. A prática em ambientes controlados, como os laboratórios oferecidos pelo PortSwigger e Hackadvisor, é fundamental para aprimorar as habilidades de detecção e mitigação dessas complexas vulnerabilidades.
