Bezbednost pametnih ugovora: i filozofija i hirurgija

Bezbednost pametnih ugovora: i filozofija i hirurgija

“A dobro, to je samo kompjuterski program — pogrešiš pa ispraviš, nije smak sveta”.

Upotreba pametnih ugovora bila je jedna od prelomnih tačaka u kratkoj istoriji Web3-ja. Horizonti mogućnosti su se odjednom proširili u svim pravcima. Svet decentralizovanih aplikacija je eksplodirao, DeFi ekosistem se oformio, a pametni ugovori su našli primenu u brojnim delatnostima: od oblasti osiguranja, preko trgovine nekretnina pa, sve do muzičke industrije.

Po definiciji, pametni ugovori su kompjuterski programi hostovani na blokčejnu koji izvršavaju predefinisane funkcije kad god korisnici interaguju sa njima. Možda zvuči kao svaki računarski program ikada, ali jedna od glavnih osobina pametnih ugovara je da su nepromenljivi, tačnije njihov kod je nemoguće izmeniti.

Ova karakteristika, koliko god donosila prednosti, ima i svoje naličje. Bilo da su u pitanju nenamerne greške ili malverzacije, eksploatacija i najmanjih slabosti pametnih ugovora može da dovede do ogromnih, a često i nenadoknadivih posledica.

Da se pozovem na prvu rečenicu, greška u pametnom ugovoru nije smak sveta, ali za onog ko je zbog te greške izgubio milione, njegov svet se zasigurno urušio.

Precizne brojeve nije lako utvrditi, ali se šteta nastala malverzacijama bolnih tačaka pametnih ugovora procenjuje na više od milijardu dolara do sada.

Jedan od najpoznatijih primera malverzacija je DAO hack iz 2016, kada je zbog vulnerabilnosti koda dogovoreno da se napravi hard fork Ethereuma gde je sva šteta poništena. Budući da se nisu svi slagali sa tom odlukom, Ethereum je tom prilikom podeljen na dva zasebna lanca: Ethereum i Ethereum Classic.

Potom Parity multisig wallet hack (2017) u kom je zbog greške u logici bespovratno zaglavljeno oko 650 miliona dolara u sadašnjoj vrednosti, ili skorašnji (februar 2022) Wormhole Cross Chain Bridge Attack kada je sa Ethereuma i Solane ukradeno čak 320 miliona dolara.

Navedeni primeri ukazuju na to da je bezbednost pametnih ugovora (koji se u slučaju Ethereuma pišu u Solidity-ju) jedan visoko zahtevan i složen proces koji direktno utiče na kvalitet protokola, ali i uspostavljanje poverenja u čitav Web3 ekosistem.

Stalno pronalaženje novih načina za hakovanje i mogućnost da čak i trivijalan propust dovede do milionskih gubitaka, nameće da čitav mindset u pristupu bezbednosti bude takav da bude takav da je spremnost na postojanje greške jedino moguće ishodište.

Zbog svega toga može se reći da je bezbednost pametnih ugovora složen sistem koji se sastoji od generalnog pristupa (filozofije ili mindset-a), samog razvoja pametnih ugovora uz poštovanje bezbednosnih procedura, poznavanja svih otkrivenih vulnerabilnosti i poznavanja i korišćenja bezbednosnih alata.

Kako naštelovati um na frekvenciju bezbednosti?

Ono što može biti zloupotrebljeno, biće.
Ako misliš da ne može biti zloupotrebljeno, promisli ponovo.
Apsolutna sigurnost ne postoji.

Možda ovakvi pomalo banalni saveti saveti okidaju anksioznost, ali to nije cilj. Ozbiljno predznanje i spremnost da se na greške reaguje pravovremeno i efikasno — e to jeste cilj. Ethereumov vodič za unapređenje pametnih ugovora koristi pomirljiv a ujedno optimističan izraz “dostojanstven pristup”. Što u principu znači nema nepogrešivih inženjera, prihvatite svoja ograničenja i slabosti i reagujte racionalno kad dođe vreme.

Vodič navodi brojne dobre prakse u generalnom pristupu bezbednosti pametnih ugovora.

Svaki novootkriveni bag i vektor napada iziskuju da se pametni ugovori iznova prošešljaju i testiraju. Svaka nova tehnika koja se pokazala korisnom zahteva da bude izučena. Isto važi i za svaki novi alat.

Jedan od najvažnijih principa u razvoju pametnih ugovora je da kompleksnost povećava verovatnoću greške. Logika pametnog ugovora treba da bude precizna i jednostavna. Modularizacija koda je prijatelj Solidity programera kao i krilatica jasnoća ispred performansi.

Kao što je rečeno, detaljno poznavanje pravca delovanja malicioznih napada je esencija bezbednosti pametnih ugovora. Zbog toga se pisanju svakog pametnog ugovora pristupa kako bi se minimizovala verovatnoća napadai. Evo kratkog pregleda nekih najpoznatijih napada.

Reentrancy attack

Jedna od najbitnijih developerskih preporuka je “biti obazriv prilikom pozivanja eksternih ugovora”. Pametni ugovori se izvršavaju imperativno — tj. čekaju da se izvrši jedna linija koda, nakon što započne naredna. Takođe, pametni ugovori mogu da pozivaju nepouzdane eksterne ugovore i čekaju rezultat pre nego što nastave izvršavanje.

Ove dve osobine pametnih ugovora ostavljaju prostor za zloupotrebu. U slučaju da je naredba uključivala neki transfer Ethera, eksterni ugovori koji se pozivaju mogu biti zlonamerno izmenjeni tako da izvuku sav Ether.

Oracle manipulation

Kako bi adekvatno funkcionisali, protokoli ponekad moraju da dobijaju informacije iz spoljnog sveta. Tj. izvršavanje određenih pametnih ugovora zavisi od informacija koje ne postoje na samom blokčejnu. Takve usluge pruža mehanizam za agregaciju eksternih informacija koji se naziva oracle, koji i sam može da bude pametni ugovor.

Problemi nastaju kada su povučene informacije netačne (a ugovor se automatski izvrši prema tim informacijama) ili su, u gorem slučaju, izmenjene tako da načine štetu. Ovakve malverzacije su izrazito česte u DeFi-ju.

Frontrunning

Ovaj napad zloupotrebljava činjenicu da su transakcije javno vidljive u mempool-u (redu koji sačinjavaju transakcije koje čekaju na izvršenje) kratak period pre nego što se kompletiraju.

To ostavlja šansu majnerima da izvrše malverzaciju transakcije pre nego što uđe u blok. Majneri mogu da manipulišu tom javnom informacijom (javno vidljivim gas fee-jem za transakciju) tako što će ponuditi veći fee kako bi se njihova transakcija prva izvršila.

Budući da ima prioritet, majner može da kupi token po određenoj ceni i s obzirom da kupovina podiže vrednost tokena (cene tokena reguliše ponuda i tražnja), instant prodajom može sebi obezbediti profit.

Griefing

Ovaj napad je moguć kod ugovora koji prihvata generičke podatke i koristi ih za pozivanje drugog ugovora putem adresscall funkcije, što je čest slučaj kod multisignature pametnih ugovora ili ugovorima sa prenosiocima transakcija (transaction relyers). Na primer kada neko želi da izvrši transakciju, ali nema dovoljno gasa za egzekuciju, može da pozove treću stranu da izvrši egzekuciju u njegovo ime. To neminovno ostavlja prostor za malverzaciju jer napadač može da sabotira transakciju šaljući nedovoljnu količnu gasa.

Ovaj napad se naziva griefing jer ne pruža nužno korist za napadača ali uvek nanosi štetu žrtvi.

Pored pomenutih, postoji još nekoliko vrsta prominentnih napada. To su Denial of Service napadi, potom napadi koji koriste aritmetička ograničenja Solidity-ja (overflow i underflow), zatim force feeding, tj. kreiranje ugovora koji primorava da Ether bude poslat na određeni cilj.

Takođe, napad timestamp dependency koristi zavisnost od ubeleženog vremena izvršene transakcije. Budući da ovo vreme generiše nod koji izvršava pametni ugovor, ono je samim tim podložno manipulaciji.

Bezbednosni alati

Solidity developeri koriste čitav niz specifičnih alata kojima vrše prevenciju štete, tj mapiraju ranjivosti pametnih ugovora i brinu se o poštovanju dobrih praksi prilikom kodiranja. Korišćenjem alata se značjno smanjuje verovatnoća napada, ali i minimizuje šteta. Alate je moguće klasifikovati u nekoliko celina.

Alati za vizualizaciju — Ovi alati se fokusiraju na vizualizaciju pametnih ugovora, EVM bajt-koda i grafove kontrole podataka.

Alati za klasifikaciju — Ovi alati su zapravo registri u kojima su klasifikovane slabosti i ranjivosti pametnih ugovora. To su npr. SWC registry i SWC pages

Alati za statičku i dinamičku analizu — Alati koji na različite načine analiziraju pametne ugovore kako bi otkrili ranjivosti i slabosti.

Linteri i formateri — Pomoću ovih alata koji primoravaju poštovanje standarda i pravila u pogledu kompozicije, povećava se čitljivost i olakšava review koda.

Alati za testiranje — Ovi alati su izrazito važni za implementaciju, merenje, praćenje i upravljanje testiranjem pametnih ugovora. Primer je Solidity Coverage.

Bezbednosne revizije koda

Jedna od osobenosti koja ide uz bezbednost pametnih ugovora je kontinuitet. Ono što je danas bug-free i “izrazito sigurno”, sutra je za nijansu nebezbednije.

Zbog toga je neophodna praksa obavljanja periodičnih bezbednosnih revizija (audita) koda i penetracionih testova kako bi se rano otkrile vulnerabilnosti pametnih ugovora, i ispravili propusti.

Revizije predstavljaju detaljnu evaluaciju izvornog koda kako bi se otkrile kritične tačke, nedostaci i loše prakse tokom developmenta. Ulazak u mindset malicioznog hakera je neophodan kako bi se sagledao čitav spektar potencijalnih rizika i mapirali svi vektori napada na svakoj liniji koda.

Premije za otkrivanje bagova

Još jedna od dobrih praksi u svetu beznednosti pametnih ugovora je i nagrađivanje developera koji otkriju bag ili vulnerabilnost u pametnom ugovoru. Sam proces je sličan reviziji koda s tim što je poziv usmeren za daleko širu zajednicu developera, etičkih hahera i stručnjaka za pametne ugovore. Ovakve masovne revizije koda mogu u značajnoj meri da doprinesu unapređenju bezbednosti unutar čitave zajednice. Jedan od primera je i Ethereum bug bounty program.

Mnogi će reći da je i najveća lepota bavljenja bezbednošću pametnih ugovora njegova nesavršenost, konstantno balansiranje kako napraviti dobar kompromis i težnja da se stvari iznova unapređuju i uvek bude korak ispred onih koji žele da načine štetu.

“Da se nauči Solidity potrebno je nedelju dana i još tri godine da se izbegne pisanje kritičnih vulnerabilnosti na dnevnom nivou.”

Neimenovani internet mudrac