Use [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) para construir e **automatizar fluxos de trabalho** com facilidade, utilizando as ferramentas comunitárias mais avançadas do mundo.\
* Você trabalha em uma **empresa de cibersegurança**? Gostaria de ver sua **empresa anunciada no HackTricks**? Ou gostaria de ter acesso à **última versão do PEASS ou baixar o HackTricks em PDF**? Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* **Junte-se ao** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo Telegram**](https://t.me/peass) ou **siga-me** no **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe suas técnicas de hacking enviando PRs para o** [**repositório hacktricks**](https://github.com/carlospolop/hacktricks) **e para o** [**repositório hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
O principal problema de abusar da Condição de Corrida é que você precisa que as solicitações sejam processadas em paralelo com uma diferença de tempo muito curta (geralmente >1ms). Na seção a seguir, são propostas diferentes soluções para tornar isso possível.
O uso de um único pacote TCP elimina completamente o efeito da variação de rede, portanto, isso claramente tem potencial para ataques de condição de corrida também. No entanto, **duas solicitações não são suficientes para um ataque de corrida confiável** devido à **variação do lado do servidor** - variações no tempo de processamento da solicitação do aplicativo causadas por variáveis incontroláveis, como contenção da CPU.
Mas, usando a técnica de '**sincronização do último byte**' do HTTP/1.1, é possível pré-enviar a maior parte dos dados retendo um pequeno fragmento de cada solicitação e, em seguida, 'completar' **20-30 solicitações com um único pacote TCP**.
* Se a solicitação não tiver corpo, envie todos os cabeçalhos, mas não defina o sinalizador END\_STREAM. Retenha um quadro de dados vazio com o sinalizador END\_STREAM definido.
* Se a solicitação tiver um corpo, envie os cabeçalhos e todos os dados do corpo, exceto o último byte. Retenha um quadro de dados contendo o último byte.
* Aguarde 100ms para garantir que os quadros iniciais tenham sido enviados.
* Verifique se o TCP\_NODELAY está desativado - é crucial que o algoritmo de Nagle agrupe os quadros finais.
* Envie um pacote de ping para aquecer a conexão local. Se você não fizer isso, a pilha de rede do sistema operacional colocará o primeiro quadro final em um pacote separado.
Observe que isso **não funciona para arquivos estáticos** em determinados servidores, mas como os arquivos estáticos não são relevantes para ataques de condição de corrida. Mas arquivos estáticos são irrelevantes para ataques de CC.
Vale ressaltar que muitos aplicativos estão atrás de um servidor de front-end, e esses servidores podem decidir encaminhar algumas solicitações por meio de conexões existentes para o back-end e criar novas conexões para outras.
Portanto, é importante não atribuir o tempo inconsistente de solicitação ao comportamento do aplicativo, como mecanismos de bloqueio que permitem apenas que uma única thread acesse um recurso de cada vez. Além disso, o roteamento de solicitações de front-end geralmente é feito com base em conexões individuais, portanto, você pode suavizar o tempo de solicitação realizando o aquecimento da conexão do lado do servidor - **enviando algumas solicitações inconsequentes pela sua conexão antes de realizar o ataque** (isso significa enviar várias solicitações antes de iniciar o ataque real)).
Alguns frameworks tentam evitar a corrupção acidental de dados usando algum tipo de **bloqueio de solicitação**. Por exemplo, o módulo de manipulador de sessão nativo do **PHP processa apenas uma solicitação por sessão de cada vez**.
É extremamente importante identificar esse tipo de comportamento, pois ele pode mascarar vulnerabilidades facilmente exploráveis. Se você perceber que todas as suas solicitações estão sendo processadas sequencialmente, tente enviá-las usando um token de sessão diferente para cada uma delas.
Usando o Turbo Intruder, você pode introduzir um pequeno atraso no lado do cliente. No entanto, como isso envolve dividir suas solicitações de ataque reais em vários pacotes TCP, você não poderá usar a técnica de ataque de um único pacote. Como resultado, em alvos com alta variação de latência, o ataque provavelmente não funcionará de forma confiável, independentemente do atraso definido.
Servidores web frequentemente **atrasam o processamento de solicitações se muitas forem enviadas rapidamente**. Ao enviar um grande número de solicitações falsas para acionar intencionalmente o limite de taxa ou recurso, você pode causar um atraso adequado no lado do servidor. Isso torna o ataque de um único pacote viável mesmo quando a execução atrasada é necessária.
Para obter mais informações sobre essa técnica, consulte o relatório original em [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
* **Tubo Intruder - Ataque de um único pacote HTTP2 (1 ponto de extremidade)**: Você pode enviar a solicitação para o **Turbo Intruder** (`Extensions` -> `Turbo Intruder` -> `Send to Turbo Intruder`), você pode alterar na solicitação o valor que deseja forçar por **`%s`** como em `csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s` e, em seguida, selecione o **`examples/race-single-packer-attack.py`** no menu suspenso:
Se o site não suportar HTTP2 (apenas HTTP1.1), use `Engine.THREADED` ou `Engine.BURP` em vez de `Engine.BURP2`.
{% endhint %}
* **Tubo Intruder - Ataque de pacote único HTTP2 (Vários endpoints)**: Caso você precise enviar uma solicitação para 1 endpoint e depois várias para outros endpoints para acionar o RCE, você pode alterar o script `race-single-packet-attack.py` para algo como:
* Também está disponível no **Repeater** através da nova opção '**Enviar grupo em paralelo**' no Burp Suite.
* Para **limit-overrun**, você pode simplesmente adicionar a **mesma solicitação 50 vezes** no grupo.
* Para **aquecimento de conexão**, você pode **adicionar** no **início** do **grupo** algumas **solicitações** para alguma parte não estática do servidor web.
* Para **atrasar** o processo **entre** o processamento **de uma solicitação e outra** em etapas de 2 subestados, você pode **adicionar solicitações extras entre** ambas as solicitações.
* Para um RC de **vários endpoints**, você pode começar enviando a **solicitação** que **vai para o estado oculto** e, em seguida, **50 solicitações** logo após isso que **exploram o estado oculto**.
* **Intruder**: Envie a **solicitação** para o **Intruder**, defina o **número de threads** para **30** dentro do menu **Opções** e selecione como payload **Cargas úteis nulas** e gere **30**.
A biblioteca `asyncio` do Python fornece suporte para programação assíncrona, permitindo que você escreva código concorrente e escalável de forma mais eficiente. Com `asyncio`, você pode lidar com tarefas assíncronas, como chamadas de rede, de forma mais eficiente, evitando bloqueios desnecessários.
A programação assíncrona é particularmente útil ao lidar com condições de corrida em aplicativos da web. Uma condição de corrida ocorre quando duas ou mais operações concorrentes tentam acessar ou modificar um recurso compartilhado ao mesmo tempo, resultando em comportamento imprevisível ou incorreto.
Ao usar `asyncio`, você pode evitar condições de corrida implementando mecanismos de exclusão mútua, como semáforos ou bloqueios, para garantir que apenas uma tarefa possa acessar o recurso compartilhado de cada vez. Isso ajuda a evitar inconsistências de dados e garantir a integridade do sistema.
Além disso, `asyncio` também oferece suporte a corrotinas, que são funções assíncronas que podem ser pausadas e retomadas posteriormente. Isso permite que você escreva código assíncrono de forma mais legível e organizada, facilitando o gerenciamento de tarefas concorrentes.
Em resumo, a biblioteca `asyncio` do Python é uma ferramenta poderosa para lidar com condições de corrida em aplicativos da web, permitindo que você escreva código assíncrono eficiente e escalável.
Este é o tipo mais básico de condição de corrida, onde **vulnerabilidades** que **aparecem** em lugares que **limitam o número de vezes que você pode executar uma ação**. Como usar o mesmo código de desconto várias vezes em uma loja online. Um exemplo muito fácil pode ser encontrado neste [**relatório**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) ou neste [**bug**](https://hackerone.com/reports/759247)**.**
Outra condição de corrida mais complicada explorará **subestados no estado da máquina** que poderiam permitir que um invasor **abusasse** de estados aos quais ele **nunca deveria ter acesso**, mas há uma **pequena janela** para o invasor acessá-lo.
O primeiro passo é identificar todos os pontos finais que gravam nele ou lêem dados dele e, em seguida, usam esses dados para algo importante. Por exemplo, os usuários podem ser armazenados em uma tabela de banco de dados que é modificada pelo registro, edição de perfil, iniciação de redefinição de senha e conclusão da redefinição de senha.
Podemos usar três perguntas-chave para descartar pontos finais que provavelmente não causarão colisões. Para cada objeto e os pontos finais associados, pergunte:
Dados armazenados em uma estrutura de dados persistente do lado do servidor são ideais para exploração. Alguns pontos finais armazenam seu estado inteiramente no lado do cliente, como redefinições de senha que funcionam enviando um JWT por e-mail - esses podem ser ignorados com segurança.
As aplicações costumam armazenar algum estado na sessão do usuário. Esses estados geralmente são um tanto protegidos contra subestados - mais sobre isso depois.
Operações que editam dados existentes (como alterar o endereço de e-mail principal de uma conta) têm grande potencial de colisão, enquanto ações que simplesmente anexam a dados existentes (como adicionar um endereço de e-mail adicional) provavelmente não serão vulneráveis a nada além de ataques de limite de estouro.
A maioria dos pontos finais opera em um registro específico, que é procurado usando uma 'chave', como um nome de usuário, token de redefinição de senha ou nome de arquivo. Para um ataque bem-sucedido, precisamos de duas operações que usem a mesma chave. Por exemplo, imagine duas implementações plausíveis de redefinição de senha:
Neste ponto, é hora de **lançar alguns ataques de RC** nos pontos finais potencialmente interessantes para tentar encontrar resultados inesperados em comparação com os regulares. **Qualquer desvio da resposta esperada**, como uma mudança em uma ou mais respostas, ou um efeito de segunda ordem, como conteúdos de e-mail diferentes ou uma mudança visível em sua sessão, pode ser uma pista indicando que algo está errado.
Quando você envia um lote de solicitações, pode descobrir que um par de solicitações iniciais aciona um estado final vulnerável, mas solicitações posteriores sobrescrevem/invalidam esse estado e o estado final não pode ser explorado. Nesse cenário, você desejará eliminar todas as solicitações desnecessárias - duas devem ser suficientes para explorar a maioria das vulnerabilidades. No entanto, reduzir para duas solicitações tornará o ataque mais sensível ao tempo, portanto, talvez seja necessário tentar o ataque várias vezes ou automatizá-lo.
Às vezes, você pode não encontrar condições de corrida, mas as **técnicas para enviar solicitações com tempo preciso** ainda podem revelar a presença de outras vulnerabilidades.
Um exemplo disso é quando **carimbos de data/hora de alta resolução são usados em vez de strings aleatórias criptograficamente** seguras para gerar tokens de segurança.
Considere um **token de redefinição de senha que é apenas randomizado usando um carimbo de data/hora**. Nesse caso, pode ser possível **acionar duas redefinições de senha para dois usuários diferentes**, que usam **o mesmo token**. Tudo o que você precisa fazer é cronometrar as solicitações para que elas gerem o mesmo carimbo de data/hora.
Para confirmar, por exemplo, a situação anterior, você pode simplesmente solicitar **2 tokens de redefinição de senha ao mesmo tempo** (usando um ataque de pacote único) e verificar se eles são **iguais**.
{% endhint %}
Verifique o [**exemplo neste laboratório**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-exploiting-time-sensitive-vulnerabilities).
[**Verifique este laboratório**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation) para ver como **pagar** em uma loja e **adicionar um item extra** que você **não precisará pagar**.
A ideia é **verificar um endereço de e-mail e alterá-lo para um diferente ao mesmo tempo** para descobrir se a plataforma verifica o novo endereço alterado.
### Alterar o e-mail para 2 endereços de e-mail baseados em cookie
De acordo com [**este artigo**](https://portswigger.net/research/smashing-the-state-machine), o Gitlab estava vulnerável a uma invasão dessa maneira porque poderia **enviar** o **token de verificação de e-mail de um e-mail para o outro e-mail**.
Você também pode verificar [**este laboratório**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint) para aprender sobre isso.
### Estados ocultos do banco de dados / Bypass de confirmação
Se **2 gravações diferentes** são usadas para **adicionar****informações** dentro de um **banco de dados**, há uma pequena parte do tempo em que **apenas os primeiros dados foram gravados** no banco de dados. Por exemplo, ao criar um usuário, o **nome de usuário** e a **senha** podem ser **gravados** e, em seguida, o token para confirmar a conta recém-criada é gravado. Isso significa que por um curto período de tempo, o **token para confirmar uma conta é nulo**.
Portanto, **registrar uma conta e enviar várias solicitações com um token vazio** (`token=` ou `token[]=` ou qualquer outra variação) para confirmar a conta imediatamente pode permitir **confirmar uma conta** em que você não controla o e-mail.
Como você pode ver, isso é de fato uma **sequência de vários passos dentro de uma única solicitação**. Mais importante ainda, ela passa por um subestado em que o **usuário temporariamente possui uma sessão válida logada**, **mas a MFA ainda não está sendo aplicada**. Um atacante poderia potencialmente explorar isso enviando uma solicitação de login juntamente com uma solicitação a um endpoint autenticado sensível.
Existem vários [**provedores de OAuth**](https://en.wikipedia.org/wiki/List\_of\_OAuth\_providers). Esses serviços permitirão que você crie um aplicativo e autentique usuários registrados pelo provedor. Para fazer isso, o **cliente** precisará **permitir que seu aplicativo** acesse alguns de seus dados dentro do **provedor de OAuth**.\
Então, até aqui, apenas um login comum com google/linkdin/github... onde você é solicitado com uma página dizendo: "_O aplicativo \<InsertCoolName> deseja acessar suas informações, você deseja permitir?_"
O **problema** ocorre quando você **aceita** e automaticamente envia um **`authorization_code`** para o aplicativo malicioso. Em seguida, esse **aplicativo abusa de uma Condição de Corrida no provedor de serviços de OAuth para gerar mais de um AT/RT** (_Authentication Token/Refresh Token_) a partir do **`authorization_code`** para sua conta. Basicamente, ele abusará do fato de você ter aceitado o aplicativo para acessar seus dados e **criará várias contas**. Então, se você **parar de permitir que o aplicativo acesse seus dados, um par de AT/RT será excluído, mas os outros ainda serão válidos**.
Depois de **obter um RT válido**, você pode tentar **abusar dele para gerar vários AT/RT** e, mesmo se o usuário cancelar as permissões para o aplicativo malicioso acessar seus dados, **vários RTs ainda serão válidos**.
No [**WS\_RaceCondition\_PoC**](https://github.com/redrays-io/WS\_RaceCondition\_PoC), você pode encontrar um PoC em Java para enviar mensagens de websocket em **paralelo** para abusar das **Condições de Corrida também em Web Sockets**.
* Você trabalha em uma **empresa de segurança cibernética**? Você quer ver sua **empresa anunciada no HackTricks**? ou você quer ter acesso à **última versão do PEASS ou baixar o HackTricks em PDF**? Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* **Junte-se ao** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-me** no **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para o** [**repositório hacktricks**](https://github.com/carlospolop/hacktricks) **e para o** [**repositório hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
Use [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) para criar e **automatizar fluxos de trabalho** com facilidade, usando as ferramentas comunitárias mais avançadas do mundo.\