Galvenais EOS viedo līgumu drošības ceļvedis. Kriptogrāfijas kopiena kļuva skeptiska, kad 2018. gada jūnijā sāka darboties pasaules lielākā ICO EOS, un tā tika iesaldēta uz 2 dienām sakarā ar programmatūras kļūda. Bet ātri uz priekšu 4 mēnešus, un EOS šodien ir vairāk nekā dubultot darījumus ko Ethereum dara šodien. Pateicoties bezmaksas un ātrāku darījumu solījumam, EOS augstākajam Dapp ir aptuveni 13 000 aktīvo lietotāju dienā, salīdzinot ar tikai 2000 Ethereum visaugstākā Dapp.

EOS viedā līguma drošība

Autors Rohans Agarvals

Dažas vispārējās viedo līgumu ievainojamības ir piemērojamas gandrīz visām platformām. Tāpat kā Ethereum, arī viedie līgumi, kas uzrakstīti uz EOS, ir jāpārbauda, ​​pirms tie sāk darboties mainnet. Nāvējošās kļūdas līgumā var tikt izmantotas, ja līgumi nav pietiekami pārbaudīti. Šajā ceļvedī mēs palīdzēsim jums izvairīties no izplatītākajām kļūmēm ceļā, lai izveidotu nākamo slepkavu dApp EOS.

Pirms rokasgrāmatas lasīšanas ir svarīgi zināt par priekšnosacījumu informāciju par EOS izstrādi, kas noderēs, kamēr lasīsit rokasgrāmatu. Zināšanas par C ++ ir obligātas. Labākā vieta, kur sākt ar viedo līgumu izstrādi, ir EOSIO dokumentācija

Darbība ar ABI dispečeru

ārpuse "C" {

spēkā neesošs (uint64_t uztvērējs, uint64_t kods, darbība uint64_t) {

klases_nosaukums šim līgumam (saņēmējs);

ja ((kods == N (eosio.token)) && (darbība == N (pārsūtīšana))) {

izpildīt&šo līgumu, &klases_nosaukums :: pārsūtīšana);

atgriešanās;

}

if (kods! = uztvērējs) atgriezties;

slēdzis (darbība) {EOSIO_API (klases_nosaukums, (darbība_1) (darbības_n))};

eosio_exit (0);

}

}

Iepriekš redzamais attēls ir modificēta ABI dispečera koda paraugs. Vienkāršāka ABI dispečers, kā parādīts zemāk, tiek izmantots, lai vienkāršāk rīkotos ar līgumu.

EOSIO_ABI (klases_nosaukums, (darbība_1) (darbības_n));

ABI dispečers / ekspeditors ļauj līgumam klausīties ienākošos eosio.token pārsūtīšanas notikumus, kā arī normālu mijiedarbību ar viedo līgumu. Lai izvairītos no nenormāliem un nelegāliem zvaniem, ir svarīgi saistīt katru galveno darbību un kodu, lai tas atbilstu prasībām.

Piemērs varētu būt hack, kas notika ar dApp EOSBet kazino kļūdas dēļ viņu ABI pārsūtīšanas avota kodā.

ja (kods == pats || kods == N (eosio.token)) {

IEVADIET šo līgumu (pats);

slēdzis (darbība) {

EOSIO_API (TIPS, DALĪBVALSTI)

}

}

Iepriekš norādītā pārbaude ABI pārsūtīšanas avota koda darbības apstrādātājā ļāva uzbrucējam pirms aplikācijas ievietošanas pilnībā apiet funkciju eosio.token :: transfer () un tieši izsaukt funkciju līguma :: transfer (), nepārsūtot EOS uz līgumu. derību. Par zaudējumiem viņam neko nemaksāja, bet viņš neko nezaudēja. Tomēr par uzvarām viņam no līguma tika izmaksāta reāla EOS.

Viņi novērsa iepriekš minēto kļūdu, pirms ienākošās darbības pieprasījuma līgumam pievienoja eosio.token līguma pārsūtīšanas darbības pārbaudi..

ja (kods == pats || kods == N (eosio.token)) {

ja (darbība == N (pārsūtīšana)) {

eosio_assert (kods == N (eosio.token), "Jānodod EOS");

}

IEVADIET šo līgumu (pats);

slēdzis (darbība) {

EOSIO_API (TIPS, DALĪBVALSTI)

}

}

Ir svarīgi izmantot izrakstu pieprasīt_auth (konts); darbībās, kuras vēlaties izpildīt tikai autorizētajā kontā. pieprasīt_auth (_pats); tiek izmantots, lai pilnvarotu tikai līguma īpašnieku parakstīt darījumu

Atļauja darbībās

void token :: pārsūtīšana (konta_nosaukums no, konta_nosaukums uz, īpašuma daudzums)

{

auto sym = daudzums.symbol.name ();

pieprasīt_saņēmējs (no);

pieprasīt_saņēmēju (uz);

auto maksātājs = has_auth (to)? uz: no;

sub_balance (no, daudzums);

pievienot_balanss (uz, daudzums, maksātājs);

}

Iepriekš minētais koda paraugs ļauj ikvienam izsaukt darbību. Lai to atrisinātu, izmantojiet Require_auth (from); paziņojums, kas pilnvaro maksātāju izsaukt darbību.

Centieties izvairīties no eosio.token līguma modificēšanas

Nesen balto cepuru hakerim tas izdevās pieprasīt 1 miljardu žetonu dapp dēļ slikti pārbaudītas metodes izsaukuma viņu eosio.token līgumā. Dapp Se7ens (tagad neaktīvs) paziņoja par jaunu metodi eosio.token līguma ietvaros, lai savus marķierus pazeminātu lietotāju kontos. Līgumā netika saukts eosio.token līguma jautājums vai pārsūtīšanas darbība, lai atspoguļotu izmaiņas un tādējādi līdzekļi maģiski parādījās lietotāju kontos. Otrkārt, viņi pirms pārsūtīšanas aizmirsa pārbaudīt metodē norādīto summu, kas ļāva hakerim procesā pieprasīt 1 miljardu savu žetonu.

Papildus maksimālā piedāvājuma un marķiera simbola maiņai ieteicams izvairīties no tā modificēšanas pielāgotajām funkcijām, jo ​​eosio.token līguma kļūdas var būt letālas. Lai droši atvieglotu lidojuma pilienu, pārsūtiet lidmašīnas marķierus uz atsevišķu kontu un izdaliet tos no turienes.

Vairāku indeksu tabulas rekvizītu modifikācija

Pašlaik EOS glabā datus koplietojamās atmiņas datu bāzē, lai koplietotu darbības.

struct [[eosio :: tabula]] persona {

konta_nosaukums;

std :: string first_name;

std :: virknes uzvārds;

std :: stīgu iela;

std :: stīgu pilsēta;

std :: virknes stāvoklis;

uint64_t primary_key () const {atgriešanās atslēga; }

};

typedef eosio :: multi_index<N (cilvēki), persona> adrese_indekss;

Iepriekš minētā koda paraugs izveido multi_index tabulu ar nosaukumu cilvēki, kuras pamatā ir šīs tabulas vienas rindas datu struktūra, izmantojot struktūras personu. EOS pašlaik neatļauj modificēt tabulas rekvizītu, tiklīdz tā tiek izvietota. eosio_assert_message apgalvojuma kļūme būs kļūda, kas tiks izmesta. Tāpēc pirms tabulas izvietošanas īpašībām jābūt pilnībā pārdomātām. Vēl jo vairāk, ir jāizveido jauna tabula ar citu nosaukumu un jāpievērš īpaša piesardzība, pārejot no vecās tabulas uz jauno. Ja tas netiks izdarīts, var tikt zaudēti dati.

Skaitliska pārpildes pārbaude

Veicot aritmētiskās darbības, vērtības var pārplūst, ja robežnosacījumi netiek pārbaudīti pietiekami atbildīgi, izraisot lietotāju aktīvu zaudēšanu.

void transfer (simbola_nosaukuma simbols, konta_nosaukums no, konta_nosaukumi uz, uint64_t atlikums) {

pieprasīt_auth (no);

konts no konta;

eosio_assert (is_balance_within_range (balance), "nederīgs atlikums");

eosio_assert (atlikums > 0, "jāpārskaita pozitīvais atlikums"); uint64_t summa = atlikums * 4; // Reizināšanas pārpilde

}

Iepriekš koda paraugā, izmantojot uint64_t Lietotāja līdzsvara apzīmēšana var izraisīt pārpildi, kad vērtība tiek reizināta. Tāpēc izvairieties no lietošanas uint64_t lai pēc iespējas apzīmētu atlikumus un veiktu aritmētiskās darbības ar to. Operācijām izmantojiet aktīvu struktūru, kas definēta eosiolibā, nevis precīzu bilanci, kas rūpējas par pārplūdes apstākļiem.

Rūpes par Līgumā pieņemtajiem pieņēmumiem

Būs pieņēmumi, kas līguma izpildes laikā prasīs apgalvojumus. Izmantojot eosio_assert, iepriekš parūpēsieties par apstākļiem un, ja apgalvojumi neizdosies, tiks apturēta konkrētās darbības izpilde. Kā piemērs –

void assert_roll_under (const uint8_t& roll_under) {

eosio_assert (roll_under >= 2 && roll_under <= 96,

"rites zem pārpildes, jābūt lielākam par 2 un mazākam par 96");

}

Iepriekš minētajā apgalvojumā ir pieņemts, ka roll_under vesels skaitlis ir lielāks par 2 & mazāk nekā 96. Bet, ja tas tā nav, iemetiet iepriekš minēto ziņojumu un pārtrauciet izpildi. Neatradšana, piemēram, iepriekš minētie stūra gadījumi, mājai, kas nosaka noteikumus, var kļūt katastrofāla.

Patiesi nejaušu skaitļu ģenerēšana

Patiesi nejaušu skaitļu ģenerēšana EOS Blockchain joprojām ir risks, ja tas nav izdarīts precīzi. Ja tas netiks izdarīts pareizi, pretinieks prognozēs rezultātus, šajā procesā spēlējot visu sistēmu. Tādi pakalpojumi kā Oracalize.it pastāv, lai nodrošinātu nejaušus skaitļus no ārēja avota, taču tie ir dārgi un ir viens kļūmes punkts. Cilvēki agrāk ir izmantojuši Blockchain kontekstuālos mainīgos (bloka numuru, bloka zīmogu utt.), Lai ģenerētu nejaušu skaitli Ethereum viedajā līgumā, taču tas ir ticis spēlēja iepriekš. Lai pareizi veiktu ģenerēšanu, programmai ir jānodrošina sava veida apvienots nejaušības princips, kuru neviena puse nevar kontrolēt atsevišķi. Viens no labākajiem iespējamajiem veidiem šobrīd ir metode, kuru ieteica pats Dens Larimars, ģenerējot nejaušu skaitli starp divām pusēm.

BountyOne emuārs: EOS viedā līguma drošība

virkne sha256_to_hex (const kontrolsumma256& sha256) {

atgriezties_hex ((char *) sha256.hash, sizeof (sha256.hash));

}

virkne sha1_to_hex (const kontrolsumma160& sha1) {

atgriezties_hex ((char *) sha1.hash, sizeof (sha1.hash));

}

veidne <T klase>

Inline void hash_combine (std :: size_t& sēklas, const T& v) {

std :: hash<T> jaucējs;

sēkla ^ = hasher (v) + 0x9e3779b9 + (sēkla << 6) + (sēkla >> 2);

}

Iepriekš sniegtais koda paraugs dod optimizētu nejaušu skaitļu ģenerēšanu no 1 līdz 100. seed1 ir mājas sēkla, un seed2 ir lietotāja sēkla iepriekš. Uzziņai, Dappub un EOSBetCasino ir atvēruši savus pilnos līgumus ar nejaušu skaitļu ģeneratoru, lai spēlētājs un māja (izstrādātājs) realizētu godīgu kauliņu spēli..

uint8_t compute_random_roll (konst kontrolsumma256& sēkla1, kontrolsumma 160& sēkla2) {

izmērs_t hash = 0;

hash_combine (hash, sha256_to_hex (sēkla1));

hash_combine (hash, sha1_to_hex (sēkla2));

atdeves hash% 100 + 1;

}

EOSBet nesen ieguva atkal uzlauzts no 65 000 EOS, kad pretinieks viltoja viņu eosio.token līgumu, lai nosūtītu EOS uz savu maku ikreiz, kad viņš veica darījumus starp saviem makiem. Eosio.token līguma kods paziņo gan EOS marķieru sūtītājam, gan saņēmējam, ka ir ienākošie marķieri. Atdarināt uzvedību & Lai atvieglotu uzlaušanu, pretinieks izveidoja divus kontus, pieņemsim, ka A & B. A bija gudrs līgums ar darbību ar paziņojumu pieprasīt_saņēmējs (N (eosbetdice11)). Kad A veicināja darījumu no A līdz B, izmantojot darbības izsaukumu, tas par to paziņoja pārsūtīšanas funkcija līgumā it kā zvans būtu nācis no eosio.token līguma. Tā kā EOS nebija reāli pārskaitīts uz līgumu, ikreiz, kad hakeris zaudēja derību, viņš neko nezaudēja, bet viņš tika apbalvots, kad uzvarēja derībā. Tādējādi nepietiek tikai ar līguma un darbības nosaukuma pārbaudi.

Līgumu paziņojumu pārbaudes

Lai mazinātu problēmu, funkcijai jāpārbauda, ​​vai līgums patiešām ir žetonu saņēmējs vai nē.

eosio_assert (transfer_data.from == _self || transfer_data.to == _self, "Jābūt ienākošai vai izejošai pārsūtīšanai");

Kādas ir labākās prakses, kas jāievēro, izstrādājot viedo līgumu par EOS?

Kļūdas ir neizbēgama jebkuras programmatūras sastāvdaļa. Tās sekas pastiprinās decentralizētā vidē, īpaši, ja tas ir saistīts ar vērtības darījumu. Papildus iepriekš apspriestajiem EOS īpašajiem drošības pasākumiem šeit ir daži vispārīgi piesardzības pasākumi un paraugprakse, kas jāpatur prātā jaunajiem viedo līgumu izstrādātājiem –

  1. Vienmēr revīzija pirms izlaišanas mainnet, līgumu neatkarīgi no trešo pušu viedo līgumu auditoru firmām.
  2. Pirms atbrīvošanas testnet, veiciet nepieciešamo Caveman atkļūdošanu (vienīgais veids, kā atkļūdot līgumu patlaban). EOSIO dokumentācijai ir a lielisks ceļvedis par to.
  3. Lai izvairītos no pārmērīgiem zaudējumiem pirmajās mainnet palaišanas dienās, nosakiet izņemšanas ierobežojuma ātrumu. Ir pieejama bug bounty programma, lai atbildīgi atklātu baltās cepures hakeri.
  4. Ja tiek atklāta kļūda, jums ir killswitch, lai iesaldētu līgumu.

Lai to ieviestu, multi_index tabulā mēs saglabājam karodziņu. Mēs iestatījām karodziņu, izmantojot darbību, kuru var izsaukt tikai līguma īpašnieks. Un tad mēs pārbaudām katru publisko rīcību, vai karogs ir iestatīts iesaldēt vai nē. Funkcijas ieviešanas paraugs ir norādīts zemāk.

struct st_frozen {

uint64_t iesaldēts;

};

typedef singleton<N (iesaldēt), st_saldēts> tb_frozen;

tb_frozen _frozen;

uint64_t getFreezeFlag () {

st_frozen frozen_st {.frozen = 0};

atgriezties _frozen.get_or_create (_self, frozen_st);

}

void setFreezeFlag (const uint64_t& pFrozen) {

st_frozen frozen_st = getFreezeFlag ();

frozen_st.frozen = pSaldēts;

_frozen.set (frozen_st, _self);

}

// publiska darbība

anulēt iesaldēt () {

pieprasīt_auth (_pats);

setFreezeFlag (1);

}

// publiska darbība

anulēt atdzesēšanu () {

pieprasīt_auth (_pats);

setFreezeFlag (0);

}

// jebkura publiska darbība

spēkā neesoša darbība (…) {

eosio_assert (getFreezeFlag (). iesaldēts == 1, "Līgums ir iesaldēts!");

}

  1. Esiet informēts par drošības uzlabojumiem bibliotēkās vai ievainojamības atklāšanu platformā. Ja nepieciešams, nekavējoties atjauniniet bibliotēkas.
  2. Atklātā pirmkoda līguma kods vismaz, lai spēlē tiktu saglabāts godīgums un indie izstrādātāji varētu daudz ātrāk atklāt kļūdas.

EOS viedā līguma drošība: secinājums

Kopš EOS palaišanas ir pagājuši tikai 5 mēneši, tomēr tas ir pieaudzis pāri cerībām. Kompromisi, kurus tā ir veikusi – DPOS, maināmi viedie līgumi, 21 kalnrūpniecības mezgls utt. Noteikti ir saskārušies ar smagu decentralizācijas maksimālistu kritiku. Neskatoties uz to, tas nav pārtraucis dApps, pamatojoties uz Ethereum, pāriet uz EOS, ņemot vērā mērogojamību, ko platforma viņiem piedāvā šodien. Vai karu uzvar EOS vai Ethereum, vēl nav izlemts, taču EOS noteikti ir uzvarējusi cīņā. Un tas paliks nemainīgs, kamēr Ethereum izdosies sasniegt pasaulei nepieciešamo mērogojamību, lai palaistu “The World Computer”..

_________________________________________________________________________________________

Šo rakstu ir uzrakstījis Rohans Agarvals

Bio – #Android Dev # Uzņēmējs # Blockchain Dev & Pētnieka līdzdibinātājs @ Cypherock.com – drošs aparatūras seifs viedtālruņiem.

Linkedin – https://www.linkedin.com/in/rohanagarwal94/

Gitūbs – https://github.com/rohanagarwal94

Twitter – https://twitter.com/rohanagarwal94

Mike Owergreen Administrator
Sorry! The Author has not filled his profile.
follow me