race_condition
Differences
This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| race_condition [2025/02/08 10:20] – created kresimir | race_condition [2025/12/01 11:40] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====Race condition==== | ====Race condition==== | ||
| - | Race condition je tip ranjivosti, koji je se najčešće pojavljuje i koristi u web sustavima kao ranjivost, no može se pojaviti i u drugim kategorijama sustava i u kombinacijama | + | Race condition je zapravo pogreška u programiranju. Događa se kad dva korisnika, ili programa, ili instance istog programa |
| - | Postoje mnogo različitih metoda kako bi se skup akcija za race condition izveo unutar ranjivog vremenskog perioda (eng. race window), koji je često jako malen, manji od sekunde. Od metoda koje serijski šalju velik broj akcija, jednu za drugom što većom brzinom, do metoda koje paralelno izvršavaju akcije, pa i do metoda koje koriste određene tehničke funkcionalnosti različitih protokola kako bi „dostavile“ skup akcija istovremeno žrtvi, iako zahtjevi ne moraju biti inicijalno generirani unutar kratkog vremenskog razmaka. | + | |
| - | Najjednostavniji primjer ovog napada jest iskorištavanje jednokratnog poklon bona ili koda za popust na web shopu više puta. Zamislimo da na serverskoj strani postoji sljedeća logika za iskorištavanje poklon bona: pri zahtjevu za korištenje bona, prvo se provjerava je li bon već iskorišten, | + | |
| - | {{racecondition: | + | Zamislimo jednostavan, |
| + | Jedan program ili njegova instanca pročita taj podatak, smanji ga za jedan i ponovno zapiše u istu memorijsku lokaciju. | ||
| + | Sve je u redu ako drugi program pročita taj broj nakon što je prvi zapisao novu vrijednost. | ||
| + | Ali problem nastaje ako drugi program pročita taj broj prije nego prvi zapiše novu vrijednost. Tada će drugi zapisati svoj broj „preko“ već izmijenjenog broja. Evo slijeda: | ||
| + | ^ U memoriji piše ^ Prvi program ^ Drugi program ^ | ||
| + | | 4 | pročita 4 | | | ||
| + | | 4 | | pročita 4 | | ||
| + | | 4 | smanji 4 za jedan | | | ||
| + | | 3 | i zapiše 3 | | | ||
| + | | 3 | | ne zna da je broj sada već smanjen na 3 i ne umanjuje za jedan od 3 već od 4 | | ||
| + | | 3 | | pa ne zapisuje ispravnih 2, već zapisuje 3 | | ||
| - | Jednostavne race condition | + | Race condition se ispravno izbjegava |
| - | Složenije race condition ranjivosti mogu zahtijevati slanje više različitih zahtjeva na dvije ili više pristupne krajnje točke (eng. Endpoints) aplikacije. Na primjer istovremeno slanje koda za potvrdu e-mail adrese, pristiglog na prvu e-mail adresu zahtjeva za promjenu e-mail adrese, gdje bi se kao rezultat potvrdila promijenjena e-mail adresa sustava, kojoj napadač nema pristup. Također, nekad prisutnost race conditiona ne omogućuje iskorištavanje ranjivosti ili napad samo po sebi, ali se može kombinirati sa drugim ranjivostima kako bi se ostvario kompleksan napad. | + | |
| - | Primjer napada pri kojoj se kombiniraju više ranjivosti bi bila neka PHP aplikacija sa funkcionalnošću koja omogućava učitavanje (eng. Upload) slike na stranicu, koja se nakon učitavanja provjerava | + | |
| - | {{racecondition: | + | Race condition se najčešće pojavljuje i koristi u web sustavima kao ranjivost, no može se pojaviti i u drugim kategorijama sustava i u kombinacijama s drugim ranjivostima. Iskorištava se tako da se skup dviju ili više akcija rade uzastopno jedna za drugom s vrlo malim vremenskim razmakom između njih, koji se naziva „race window“ ili prozor utrke. Ciljevi i posljedice ovog tipa napada su razni, jer se ova ranjivost pojavljuje u mnogo oblika i u više različitih okruženja. |
| - | ===PRIMJER - Zadatak s Hacknite platforme – Formule | + | Postoji mnogo različitih metoda kako bi se skup akcija za race condition izveo unutar ranjivog vremenskog perioda |
| - | ¸¸ | + | Najjednostavniji primjer ovog napada jest iskorištavanje jednokratnog poklon bona ili koda za popust na web shopu više puta. Zamislimo da na serverskoj strani postoji sljedeća logika za iskorištavanje poklon bona: |
| - | Jura je jako voli utrke pa je odlučio napraviti svoj web shop u kojem će prodavati stvari | + | * pri zahtjevu za korištenje bona, prvo se provjerava |
| - | Kako bi promovirao svoj web shop i potaknu ljude na kupnju, svim stvorenim računima Jura je odlučio dodijeliti 10 Eura i jednokratni popust za prvu kupnju od 25%. | + | * ako nije onda se poklon bon dodaje u obračun i |
| - | Iako na računu nemate dovoljno iznosa za kupovinu artikla, postoji li način | + | * postavlja se zastavica |
| - | ¸¸ | + | |
| - | Čitajući tekst zadatka, mogu se primijetiti hintovi koji ukazuju na race condition. | + | Vremenski prozor između ove dvije operacija, provjere je li poklon bon već iskorišten |
| - | Nakon iskorištavanja popusta, na kratko | + | |
| - | Nakon toga se ponovno prikazuje stranica, sa iskorištenim popustom | + | |
| - | {{racecondition: | + | {{ racecondition: |
| - | Gumbi „Iskoristi popust“ | + | Jednostavne race condition ranjivosti uglavnom zahtijevaju slanje većeg broja istih zahtjeva unutar ranjivog vremenskog perioda |
| - | Kako bi se testiralo je li ova funkcionalnost ranjiva na race condition, može se koristiti | + | |
| - | Može se koristiti | + | |
| - | Oblik skripte je definiran sljedećim izrazom: | + | |
| - | ¸¸ | + | |
| - | for (let i = 0; i < N; i++) { fetch("/ | + | |
| - | ¸¸ | + | |
| - | Gdje je N broj uzastopnih zahtjeva koji se šalju. Ova skripta se može pokrenuti | + | |
| - | {{racecondition: | + | Složenije race condition ranjivosti mogu zahtijevati slanje više različitih zahtjeva na dvije ili više pristupnih krajnjih točkaka (eng. Endpoints) aplikacije. Na primjer istovremeno slanje koda za potvrdu e-mail adrese, pristiglog na prvu e-mail adresu zahtjeva za promjenu e-mail adrese, gdje bi se kao rezultat potvrdila promijenjena e-mail adresa sustava, kojoj napadač nema pristup. Također, nekad prisutnost race conditiona ne omogućuje iskorištavanje ranjivosti ili napad sama po sebi, ali se može kombinirati s drugim ranjivostima kako bi se ostvario kompleksan napad. |
| - | Nakon pokretanje skripte za N = 10 i osvježavanja stranica, iskorišteni popust je -175%, a cijena još veća nego prije. Ovo naznačuje da je race condition ranjivost prisutna. Prikazano na slici 5. | + | Primjer napada pri kojoj se kombinira više ranjivosti bi bila neka PHP aplikacija s funkcionalnošću koja omogućava učitavanje (eng. Upload) slike na stranicu, a koju nakon učitavanja provjerava |
| - | {{racecondition: | + | Kompliciraniji primjer napada bio bi u slučaju kad se poslana datoteka provjerava procesom koji traje pola sekunde, nakon čega se uklanja iz sustava, ali se u unutar tih pola sekunde ta datoteka, zapravo zlonamjerna skripta, može dohvatiti i pokrenuti na drugoj pristupnoj krajnjoj točki. Ovo je primjer korištenja race condition ranjivosti kako bi se omogućilo izvršavanje naredbi. Ovaj napad je prikazan na slici 2. |
| - | Uzevši u obzir da je prije pokretanja skripte, akcija pridružena putanji bila „Makni popust“, može se zaključiti da se ta akcija izvršila 8 puta, oduzimajući 200% popusta od originalnih 25%, rezultirajući krajnjim popustom od -175%. | + | {{ racecondition: |
| - | + | ||
| - | Stvaranjem novog korisnika ponovno se dolazi do početnog stanja bez iskorištenog popusta gdje je akcija pridružena uz putanju „/ | + | |
| - | + | ||
| - | {{racecondition: | + | |
| - | + | ||
| - | Ponovnim pokretanjem skripte, uz N=4, u stanju sustava dok popust nije postavljen a predviđena akcija je postavljanje popusta, uspješno se upotrjebljuje popust od 25% 4 puta, rezultirajući popustom od 100%, nakon čega je cijena 0. Prikazano na slici 7. | + | |
| - | + | ||
| - | {{racecondition: | + | |
| - | + | ||
| - | Pritiskom na gumb „Buy“ uspješno se izvršava kupnja i dobiva rješenje zadatka. | + | |
| ===PRIMJER - Zadatak s Hacknite platforme - Pizza=== | ===PRIMJER - Zadatak s Hacknite platforme - Pizza=== | ||
| - | + | < | |
| - | ¸¸ | + | Netko je hakirao stranicu za glasanje - pizza s ili bez ananasa? Nema drugog objašnjenja zašto bi pizza s ananasom imala više glasova. Možeš li upotrijebiti svoje hakerske vještine i spasiti glasanje - učiniti da ispravna pizza (bez ananasa!!) pobijedi? |
| - | Netko je hakirao stranicu za glasanje - pizza s ili bez ananasa? Nema drugog objašnjenja zašto bi pizza s ananasom imala više glasova.. Možeš li upotrijebiti svoje hakerske vještine i spasiti glasanje - učiniti da ispravna pizza (bez ananasa!!) pobijedi? | + | |
| Dostupan ti je izvorni kod web aplikacije | Dostupan ti je izvorni kod web aplikacije | ||
| http:// | http:// | ||
| - | ¸¸ | + | </ |
| Uz zadatak je dostupan i izvorni kod zadatka. | Uz zadatak je dostupan i izvorni kod zadatka. | ||
| - | Pristupom stranici zadatka, prikazane su dvije opcije glasanja, pizza s ananasom i pizza bez ananasa. Nakon odabira jedne opcije pritiskom na gumb “Glasaj”, | + | Pristupom stranici zadatka, prikazane su dvije opcije glasanja, pizza s ananasom i pizza bez ananasa. Nakon odabira jedne opcije pritiskom na gumb “Glasaj”, |
| - | {{racecondition: | + | {{ racecondition: |
| - | Analizom HTML koda stranice u inicijalnom stanju (brisanjem kolačića, postavlja se u inicijalno stanje) koristeći razvojne alate web preglednika, | + | Analizom HTML koda stranice u inicijalnom stanju (brisanjem kolačića, postavlja se u inicijalno stanje) koristeći razvojne alate web preglednika, |
| - | {{racecondition: | + | {{ racecondition: |
| - | Analizom izvornog koda za glasanje na putanji „/ | + | Analizom izvornog koda za glasanje na putanji „/ |
| - | {{racecondtion: | + | {{ racecondtion: |
| Koristeći isti pristup stvaranja JavaScript skripte za slanje više uzastopnih zahtjeva, skripta je definirana u sljedećem izrazu: | Koristeći isti pristup stvaranja JavaScript skripte za slanje više uzastopnih zahtjeva, skripta je definirana u sljedećem izrazu: | ||
| - | ¸¸ | + | < |
| for (let i = 0; i < N; i++) { | for (let i = 0; i < N; i++) { | ||
| fetch("/ | fetch("/ | ||
| Line 83: | Line 68: | ||
| body: new URLSearchParams({ vote: " | body: new URLSearchParams({ vote: " | ||
| } | } | ||
| - | ¸¸ | + | </ |
| - | Gdje je N broj uzastopnih zahtjeva koji će se slati. Pokretanjem ove skripte, | + | Gdje je N broj uzastopnih zahtjeva koji će se slati. Pokretanjem ove skripte, |
| Ponovnim pokretanjem skripte, broj glasova se više ne mijenja. Detaljnijom analizom koda, vidi se da nakon što je jednom glas postavljen, ponovno slanje istog glasa izbacuje pogrešku, te ne može promijeniti sustav. Prikazano na slici 11. | Ponovnim pokretanjem skripte, broj glasova se više ne mijenja. Detaljnijom analizom koda, vidi se da nakon što je jednom glas postavljen, ponovno slanje istog glasa izbacuje pogrešku, te ne može promijeniti sustav. Prikazano na slici 11. | ||
| - | {{racecondition: | + | {{ racecondition: |
| - | Znamo da je race window pri inicijalnom postavljanju glasa dovoljno velik da uspijemo broj glasova povećati za 6, naprednijim tehnikama i više, no potreban broj glasova da bi glasanje za pizzu bez ananasa pobijedilo je preko 200. Analizom koda za promjenu odabira glasa, vidi se da jest taj kod također ranjiv na race condition. Može se zaključiti da se postupak za dodavanje 200 glasova sastoji od slanja većeg broja glasova za željenu opciju, koji prolaze kroz race window te odabira druge opcije kako bi se opet omogućilo slanje novog skupa zahtjeva na željenu opciju koji će opet povećati broj glasova. | + | Znamo da je race window pri inicijalnom postavljanju glasa dovoljno velik da uspijemo broj glasova povećati za 6, a naprednijim tehnikama i više, no potreban broj glasova da bi glasanje za pizzu bez ananasa pobijedilo je preko 200. Analizom koda za promjenu odabira glasa, vidi se da je taj kod također ranjiv na race condition. Može se zaključiti da se postupak za dodavanje 200 glasova sastoji od slanja većeg broja glasova za željenu opciju, koji prolaze kroz race window te potom odabira druge opcije kako bi se opet omogućilo slanje novog skupa zahtjeva na željenu opciju koji će opet povećati broj glasova. |
| - | Kako bi to postigli, inicijalna skripta se mora proširiti | + | Kako bi to postigli, inicijalna skripta se mora proširiti |
| - | Znamo da je race window pri inicijalnom postavljanju glasa dovoljno velik da uspijemo broj glasova povećati za 6, naprednijim tehnikama i više, no potreban broj glasova da bi glasanje za pizzu bez ananasa pobijedilo je preko 200. Analizom koda za promjenu odabira glasa, vidi se da jest taj kod također ranjiv na race condition. Može se zaključiti da se postupak za dodavanje 200 glasova sastoji od slanja većeg broja glasova za željenu opciju, koji prolaze kroz race window te odabira druge opcije kako bi se opet omogućilo slanje novog skupa zahtjeva na željenu opciju koji će opet povećati broj glasova. | + | < |
| - | + | ||
| - | Kako bi to postigli, inicijalna skripta se mora proširiti sa još jednom for petljom, koja će nakon svakog slanja skupa zahtjeva za željenu opciju, poslati jedan zahtjev za drugu opciju, kako bi opet otvorilo mogućnost slanja novog skupa zahtjeva za željenu opciju. Modificirana skripta je prikazana u nastavku. | + | |
| - | ¸¸ | + | |
| for (let i = 0; i < M; i++) { | for (let i = 0; i < M; i++) { | ||
| for (let i = 0; i < N; i++) { | for (let i = 0; i < N; i++) { | ||
| Line 105: | Line 87: | ||
| fetch("/ | fetch("/ | ||
| } | } | ||
| - | ¸¸ | + | </ |
| - | Gdje je broj N, broj slanja uzastopnih glasova za željenu opciju, a broj M broj ponavljanja skupa operacija koji se sastoji od slanja N zahtjeva na željenu opciju te odabira druge opcije kako bi se ponovno omogućilo poslati novi skup zahtjeva za željenu opciju. | + | Gdje je broj N, broj slanja uzastopnih glasova za željenu opciju, a broj M je broj ponavljanja skupa operacija koji se sastoji od slanja N zahtjeva na željenu opciju te odabira druge opcije kako bi se ponovno omogućilo poslati novi skup zahtjeva za željenu opciju. |
| Računajući da je N = 10, a M = 50, poslat će se ukupno 550 zahtjeva (500 zahtjeva za željenu opciju i 50 zahtjeva za drugu opciju). Zna se da će svaka skupina od 10 glasova za željenu opciju povećati broj glasova za 6, što bi uz 50 ponavljanja trebalo povećati broj ukupnih glasova za željenu opciju za otprilike 300. | Računajući da je N = 10, a M = 50, poslat će se ukupno 550 zahtjeva (500 zahtjeva za željenu opciju i 50 zahtjeva za drugu opciju). Zna se da će svaka skupina od 10 glasova za željenu opciju povećati broj glasova za 6, što bi uz 50 ponavljanja trebalo povećati broj ukupnih glasova za željenu opciju za otprilike 300. | ||
| - | Nakon pokretanja ove skripte, broj glasova za pizzu bez ananasa je povećano iznad broja glasova za pizzu zadataka | + | Nakon pokretanja ove skripte, broj glasova za pizzu bez ananasa je povećan iznad broja glasova za pizzu koje traži zadatak, čime je zadatak |
| Line 119: | Line 101: | ||
| ===Zaštita od race conditiona=== | ===Zaštita od race conditiona=== | ||
| - | Race condition ranjivost se može pojaviti u više oblika i u raznim funkcionalnostima, | + | Race condition ranjivost se može pojaviti u više oblika i u raznim funkcionalnostima, |
| - | | + | |
| - | Također treba izbjegavati postepeno stvaranje objekata, gdje je objekt pri stvaranju u nedovršenom međustanju. Na primjer pri stvaranju novog korisnika u sustavu, prvo se izvodi jedna SQL transakcija za stvaranje dijela korisničkih podataka, onda se vrše druge operacije, pa se izvodi druga SQL operacija za stvaranje ostataka korisničkih podataka novog korisnika u bazi. Ovisno o funkcionalnostima, | + | |
| - | | + | |
| + | Mogu se koristiti ključevi za čitanje i ključevi za pisanje, gdje može istovremeno biti postavljeno više ključeva za čitanje na isti resurs, ali ključ za pisanje ne može biti postavljen istovremeno s drugim ključem za čitanje ili pisanje. Ovo rješenje ponekad može biti nepraktično, | ||
| + | | ||
| + | |||
| + | Također treba izbjegavati postupno stvaranje objekata, gdje je objekt tijekom stvaranja u nedovršenom međustanju. Na primjer, pri stvaranju novog korisnika u sustavu, prvo se izvodi jedna SQL transakcija za stvaranje dijela korisničkih podataka, onda se vrše druge operacije, pa se izvodi druga SQL operacija za stvaranje ostatka korisničkih podataka novog korisnika u bazi. Ovisno o funkcionalnostima, | ||
| + | Važno je biti svjestan postojanja ove ranjivosti pri pisanju koda, paziti na redoslijed i razmak između operacija za provjeravanje i korištenje resursa i napraviti odgovarajuće promjene dizajna ako se uobičajena i gotova rješenja ne mogu koristiti. Napisani kod se može kasnije analizirati alatima za statičku analizu koda koji imaju mogućnost detekcije race conditiona te se ciljani dio koda također može testirati pod opterećenjem, | ||
race_condition.1739010054.txt.gz · Last modified: 2025/12/01 11:40 (external edit)