hacktricks/pentesting-web/race-condition.md
2024-02-10 13:11:20 +00:00

19 KiB

Trkački uslov


Koristite Trickest da biste lako izgradili i automatizovali radne tokove koji se pokreću najnaprednijim alatima zajednice na svetu.
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 sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u:

{% hint style="warning" %} Da biste duboko razumeli ovu tehniku, proverite originalni izveštaj na https://portswigger.net/research/smashing-the-state-machine {% endhint %}

Unapređivanje napada trkačkog uslova

Glavna prepreka u iskorišćavanju trkačkog uslova je osigurati da se više zahteva obrađuje istovremeno, sa vrlo malom razlikom u vremenu obrade - idealno manje od 1ms.

Ovde možete pronaći neke tehnike za sinhronizaciju zahteva:

Napad jednim paketom HTTP/2 protiv sinhronizacije poslednjeg bajta HTTP/1.1

  • HTTP/2: Podržava slanje dva zahteva preko jedne TCP konekcije, smanjujući uticaj mrežnog kašnjenja. Međutim, zbog varijacija na serverskoj strani, dva zahteva možda nisu dovoljna za dosledno iskorišćavanje trkačkog uslova.
  • HTTP/1.1 'Last-Byte Sync': 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. Zaustavljanje na 100ms nakon početnog slanja.
  3. Onemogućavanje TCP_NODELAY da bi se koristio Naglov algoritam za grupisanje konačnih 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. Ova metoda se ne primenjuje na statičke datoteke koje obično nisu uključene u napade trkačkog uslova.

Prilagođavanje serverske arhitekture

Razumevanje arhitekture cilja je ključno. Serveri na prednjoj strani mogu usmeravati zahteve na različite načine, što utiče na vreme. Preemptivno zagrevanje serverske veze, putem nebitnih zahteva, može normalizovati vreme zahteva.

Prevazilaženje zaključavanja na osnovu sesije

Okviri kao što je PHP-ov rukovalac sesijama serijski obrađuju zahteve po sesiji, što potencijalno prikriva 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 stvaranjem kašnjenja na serverskoj strani pogodnog za trkačke uslove.

Primeri napada

  • Tubo Intruder - napad jednim paketom HTTP2 (1 endpoint): Možete poslati zahtev na Turbo intruder (Extensions -> Turbo Intruder -> Send to Turbo Intruder), možete promeniti vrednost koju želite da probate metodom "brute force" za %s kao u csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s, a zatim izabrati examples/race-single-packer-attack.py iz padajućeg menija:

Ako želite da pošaljete različite vrednosti, možete izmeniti kod sa ovim koji koristi listu reči sa clipboard-a:

passwords = wordlists.clipboard
for password in passwords:
engine.queue(target.req, password, gate='race1')

{% hint style="warning" %} Ako veb ne podržava HTTP2 (samo HTTP1.1), umesto Engine.BURP2 koristite Engine.THREADED ili Engine.BURP. {% endhint %}

  • Tubo Intruder - Napad jednim paketom HTTP2 (Više krajnjih tačaka): U slučaju da trebate poslati zahtev na jednu krajnju tačku, a zatim više zahteva na druge krajnje tačke kako biste pokrenuli RCE, možete promeniti skriptu race-single-packet-attack.py na nešto poput:
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 'Paralelno slanje grupe' u Burp Suite-u.
  • Za prekoračenje ograničenja jednostavno možete dodati istu zahtev 50 puta u grupu.
  • Za zagrevanje konekcije, možete dodati na početak grupe neke zahteve ka delu veb servera koji nije statičan.
  • 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še krajnjih tačaka RC-a možete početi slanje zahteva koji ide ka skrivenom stanju i zatim 50 zahteva odmah nakon toga koji eksploatišu skriveno stanje.

Sirovi BF

Prethodno istraživanje je koristilo ove payload-e koji su samo pokušavali da pošalju pakete što je brže moguće kako bi izazvali RC.

  • Repeater: Pogledajte primere iz prethodne sekcije.
  • Intruder: Pošaljite zahtev Intruder-u, postavite broj niti na 30 unutar menija Opcije, izaberite kao payload Null payloads i generišite 30.
  • Turbo Intruder
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 - asyncio

Python - asyncio je biblioteka koja omogućava asinhrono izvršavanje koda. To je korisno za rukovanje trkačkim uslovima u veb aplikacijama.

Da biste iskoristili asyncio, morate koristiti async i await ključne reči. async se koristi za definisanje asinhronih funkcija, dok se await koristi za čekanje na završetak asinhronih operacija.

Kada se koristi asyncio, možete koristiti asyncio.Lock() objekat za sinhronizaciju pristupa deljenim resursima. Ovaj objekat obezbeđuje da samo jedan proces može pristupiti resursu u isto vreme.

Evo primera koda koji koristi asyncio za rukovanje trkačkim uslovima:

import asyncio

async def access_resource(lock):
    await lock.acquire()
    try:
        # Ovde se vrši pristup deljenom resursu
        print("Pristupam deljenom resursu...")
        await asyncio.sleep(1)
        print("Završio sam pristup deljenom resursu.")
    finally:
        lock.release()

async def main():
    lock = asyncio.Lock()
    tasks = []
    for _ in range(5):
        tasks.append(access_resource(lock))
    await asyncio.gather(*tasks)

asyncio.run(main())

U ovom primeru, access_resource() funkcija koristi lock.acquire() da bi se osiguralo da samo jedan proces može pristupiti deljenom resursu u isto vreme. Nakon pristupa resursu, funkcija čeka 1 sekundu koristeći asyncio.sleep() i zatim oslobađa zaključavanje pomoću lock.release().

main() funkcija kreira asyncio.Lock() objekat i pokreće pet instanci access_resource() funkcije koristeći asyncio.gather().

Kada se ovaj kod izvrši, svaka instanca access_resource() funkcije će se izvršiti asinhrono, ali će biti sinhronizovane korišćenjem asyncio.Lock() objekta. Ovo osigurava da samo jedan proces može pristupiti deljenom resursu u isto vreme, sprečavajući trkačke uslove.

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-a

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 određenu radnju. Na primer, korišćenje istog koda za popust nekoliko puta u veb prodavnici. Veoma jednostavan primer može se pronaći u ovom izveštaju ili u ovom bagu.

Postoji mnogo varijacija ovakvih napada, uključujući:

  • Višestruko iskorišćavanje poklon kartice
  • Višestruko ocenjivanje proizvoda
  • Podizanje ili prenos gotovine preko iznosa na računu
  • Ponovno korišćenje jedinstvenog rešenja CAPTCHA
  • Zaobilaženje ograničenja brzine protiv brute-force napada

Skriveni podstanja

Iskorišćavanje složenih trka uslova često uključuje iskorišćavanje kratkih prilika za interakciju sa skrivenim ili nenamernim podstanjima mašine. Evo kako pristupiti ovome:

  1. Identifikujte potencijalna skrivena 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 za resetovanje lozinke. Fokusirajte se na:
  • Skladištenje: Dajte prednost krajnjim tačkama koje manipulišu podacima na serveru u odnosu na one koje rukuju podacima na klijentskoj strani.
  • Radnja: Potražite operacije koje menjaju postojeće podatke, jer su one verovatnije da će stvoriti iskorišćive uslove u poređenju sa operacijama koje dodaju nove podatke.
  • Ključevi: Uspešni napadi obično uključuju operacije koje se ključe na isti identifikator, na primer korisničko ime ili token za resetovanje.
  1. Sprovedite početno ispitivanje
  • 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 ukazivati na ranjivost.
  1. Pokažite ranjivost
  • Sužite napad na minimalan broj zahteva potrebnih za iskorišćavanje ranjivosti, često samo dva. Ovaj korak može zahtevati više pokušaja ili automatizaciju zbog preciznog vremenskog usklađivanja.

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 može omogućiti identične tokene za istovremene zahteve.

Da biste iskoristili:

  • Koristite precizno vremensko slanje, poput napada sa jednim paketom, kako biste izvršili istovremene zahteve za resetovanje lozinke. Identični tokeni ukazuju 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 da biste isprobali ovo.

Studije slučaja skrivenih podstanja

Plaćanje i dodavanje stavke

Proverite ovaj PortSwigger Lab da biste videli kako platiti u prodavnici i dodati dodatnu stavku koju nećete morati platiti.

Potvrda drugih e-pošta

Ideja je verifikovati adresu e-pošte i istovremeno je promeniti u drugu kako biste saznali da li platforma verifikuje novu adresu.

Promena e-pošte na 2 adrese zasnovana na kolačićima

Prema ovom istraživanju, Gitlab je bio ranjiv na preuzimanje na ovaj način jer bi mogao poslati token za verifikaciju e-pošte jedne adrese na drugu adresu.

Proverite ovaj PortSwigger Lab da biste isprobali ovo.

Skrivena stanja baze podataka / Zaobilaženje potvrde

Ako se koriste 2 različita upisa za dodavanje informacija u bazu podataka, postoji mali vremenski period kada je samo prvi podatak upisan u bazu podataka. Na primer, prilikom kreiranja korisnika, korisničko ime i lozinka mogu biti upisani, a zatim se upisuje token za potvrdu novo kreiranog naloga. To znači da je tokom kratkog vremena token za potvrdu naloga prazan.

Stoga, registrovanje naloga i slanje nekoliko zahteva sa praznim tokenom (token= ili token[]= ili bilo koja druga varijacija) za odmah potvrđivanje naloga može omogućiti potvrdu naloga gde ne kontrolišete e-poštu.

Proverite ovaj PortSwigger Lab da biste isprobali ovo.

Zaobilaženje dvofaktorne autentifikacije

Sledeći pseudo-kod je ranjiv na trku uslova jer u vrlo kratkom vremenskom periodu dvofaktorna autentifikacija nije primenjena dok se sesija kreira:

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 postojanost OAuth2

Postoji nekoliko OAuth provajdera. 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-a.
Dakle, do sada samo uobičajena prijava putem google/linkedin/github... gde vam se prikazuje stranica sa porukom: "Aplikacija <InsertCoolName> želi da pristupi vašim informacijama, da li želite da to dozvolite?"

Trkačka situacija u authorization_code

Problem se javlja kada ga prihvatite i automatski šalje authorization_code zlonamerno aplikaciji. Zatim, ova aplikacija zloupotrebljava trkačku situaciju u OAuth servis provajderu 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 prihvatili aplikaciju da pristupi vašim podacima da bi kreirala nekoliko naloga. Zatim, ako prestane da dozvoljava aplikaciji pristup vašim podacima, jedan par AT/RT će biti obrisan, ali ostali će i dalje biti validni.

Trkačka situacija u Refresh Token

Kada ste dobili validan RT, možete pokušati da ga zloupotrebite da biste generisali nekoliko AT/RT-a i čak ako korisnik otkaže dozvole za zlonamernu aplikaciju da pristupi njegovim podacima, nekoliko RT-ova će i dalje biti validno.

RC u WebSockets

U WS_RaceCondition_PoC možete pronaći PoC u Javi za slanje websocket poruka paralelno kako biste zloupotrebili trkačke situacije i u Web Sockets-ima.

Reference

Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u:


Koristite Trickest da biste lako izgradili i automatizovali radne tokove uz pomoć najnaprednijih alata zajednice.
Dobijte pristup danas:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}