【慢霧】EOS智能合約最佳安全開(kāi)發(fā)指南區(qū)塊鏈

                  鏈向財(cái)經(jīng) 2018-10-01 23:32
                  分享到:
                  導(dǎo)讀

                  本文由慢霧(SlowMist)同學(xué)主導(dǎo),麒麟小組以及其他同學(xué)參與,旨在為EOS智能合約開(kāi)發(fā)人員提供一些智能合約的安全準(zhǔn)則及已知漏洞分析。https://github.com/slowmist/eos-smart-contract-security-best-practices

                  目錄

                  • 安全準(zhǔn)則

                  • 已知漏洞

                            1.  數(shù)值溢出

                                  1.1 漏洞示例

                                  1.2 防御方法

                                  1.3 真實(shí)案例

                             2. 權(quán)限校驗(yàn)

                                   2.1 漏洞示例

                                   2.2 防御方法

                                   2.3 真實(shí)案例

                              3. apply 校驗(yàn) 

                                   3.1 漏洞示例

                                   3.2 防御方法

                                   3.3 真實(shí)案例

                  • 參考文獻(xiàn)

                  • 致謝

                  安全準(zhǔn)則

                  EOS 處于早期階段并且有很強(qiáng)的實(shí)驗(yàn)性質(zhì)。因此,隨著新的 bug 和安全漏洞被發(fā)現(xiàn),新的功能不斷被開(kāi)發(fā)出來(lái),其面臨的安全威脅也是不斷變化的。這篇文章對(duì)于開(kāi)發(fā)人員編寫(xiě)安全的智能合約來(lái)說(shuō)只是個(gè)開(kāi)始。

                  開(kāi)發(fā)智能合約需要一個(gè)全新的工程思維,它不同于我們以往項(xiàng)目的開(kāi)發(fā)。因?yàn)樗稿e(cuò)的代價(jià)是巨大的,很難像中心化類(lèi)型的軟件那樣,打上補(bǔ)丁就可以彌補(bǔ)損失。就像直接給硬件編程或金融服務(wù)類(lèi)軟件開(kāi)發(fā),相比于 Web 開(kāi)發(fā)和移動(dòng)開(kāi)發(fā)都有更大的挑戰(zhàn)。因此,僅僅防范已知的漏洞是不夠的,還需要學(xué)習(xí)新的開(kāi)發(fā)理念:

                  • 對(duì)可能的錯(cuò)誤有所準(zhǔn)備

                  任何有意義的智能合約或多或少都存在錯(cuò)誤,因此你的代碼必須能夠正確的處理出現(xiàn)的 bug 和漏洞。需始終保證以下規(guī)則:

                  1.當(dāng)智能合約出現(xiàn)錯(cuò)誤時(shí),停止合約;

                  2.管理賬戶(hù)的資金風(fēng)險(xiǎn),如限制(轉(zhuǎn)賬)速率、最大(轉(zhuǎn)賬)額度;

                  3.有效的途徑來(lái)進(jìn)行 bug 修復(fù)和功能提升。

                  • 謹(jǐn)慎發(fā)布智能合約

                  盡量在正式發(fā)布智能合約之前發(fā)現(xiàn)并修復(fù)可能的 bug。

                  1.對(duì)智能合約進(jìn)行徹底的測(cè)試,并在任何新的攻擊手法被發(fā)現(xiàn)后及時(shí)的測(cè)試(包括已經(jīng)發(fā)布的合約)

                  2.從 alpha 版本在麒麟測(cè)試網(wǎng)(CryptoKylin-Testnet)上發(fā)布開(kāi)始便邀請(qǐng)專(zhuān)業(yè)安全審計(jì)機(jī)構(gòu)進(jìn)行審計(jì),并提供漏洞賞金計(jì)劃(Bug Bounty)

                  3.階段性發(fā)布,每個(gè)階段都提供足夠的測(cè)試

                  • 保持智能合約的簡(jiǎn)潔

                  復(fù)雜會(huì)增加出錯(cuò)的風(fēng)險(xiǎn)。

                  1.確保智能合約邏輯簡(jiǎn)潔;

                  2.確保合約和函數(shù)模塊化;

                  3.使用已經(jīng)被廣泛使用的合約或工具(比如,不要自己寫(xiě)一個(gè)隨機(jī)數(shù)生成器);

                  4.條件允許的話,清晰明了比性能更重要;

                  5.只在你系統(tǒng)的去中心化部分使用區(qū)塊鏈。

                  • 保持更新

                  通過(guò)公開(kāi)資源來(lái)確保獲取到最新的安全進(jìn)展。

                  1.在任何新的漏洞被發(fā)現(xiàn)時(shí)檢查你的智能合約;

                  2.盡可能快的將使用到的庫(kù)或者工具更新到最新;

                  3.使用最新的安全技術(shù)。

                  • 清楚區(qū)塊鏈的特性

                  盡管你先前所擁有的編程經(jīng)驗(yàn)同樣適用于智能合約開(kāi)發(fā),但這里仍然有些陷阱你需要留意:

                  require_recipient(account_name name) 可觸發(fā)通知,調(diào)用name合約中的同名函數(shù),官方文檔

                  https://developers.eos.io/eosio-cpp/v1.2.0/reference#section-require_recipient

                  已知漏洞

                  數(shù)值溢出

                  在進(jìn)行算術(shù)運(yùn)算時(shí),未進(jìn)行邊界檢查可能導(dǎo)致數(shù)值上下溢,引起智能合約用戶(hù)資產(chǎn)受損。

                  1.漏洞示例

                  存在缺陷的代碼:batchTransfer 批量轉(zhuǎn)賬

                  typedef struct acnts {account_name name0;account_name name1;account_name name2;account_name name3;} account_names;void batchtransfer(symbol_name symbol, account_name from, account_names to, uint64_t balance){    require_auth(from);account fromaccount;    require_recipient(from);    require_recipient(to.name0);    require_recipient(to.name1);    require_recipient(to.name2);    require_recipient(to.name3);    eosio_assert(is_balance_within_range(balance), "invalid balance");    eosio_assert(balance > 0, "must transfer positive balance");    uint64_t amount = balance * 4; //乘法溢出int itr = db_find_i64(_self, symbol, N(table), from);    eosio_assert(itr >= 0, "Sub-- wrong name");    db_get_i64(itr, &fromaccount, (account));    eosio_assert(fromaccount.balance >= amount, "overdrawn balance");    sub_balance(symbol, from, amount);    add_balance(symbol, to.name0, balance);    add_balance(symbol, to.name1, balance);    add_balance(symbol, to.name2, balance);    add_balance(symbol, to.name3, balance);}

                  2.防御方法

                  盡可能使用 asset 結(jié)構(gòu)體進(jìn)行運(yùn)算,而不是把 balance 提取出來(lái)進(jìn)行運(yùn)算。

                  3.真實(shí)案例

                  【EOS Fomo3D你千萬(wàn)別玩】狼人殺遭到溢出攻擊, 已經(jīng)涼涼(https://bihu.com/article/995093)

                  權(quán)限校驗(yàn)

                  在進(jìn)行相關(guān)操作時(shí),應(yīng)嚴(yán)格判斷函數(shù)入?yún)⒑蛯?shí)際調(diào)用者是否一致,使用require_auth進(jìn)行校驗(yàn)。

                  1.漏洞示例

                  存在缺陷的代碼:transfer 轉(zhuǎn)賬

                  void token::transfer( account_name from,account_name to,asset        quantity,string       memo ){    eosio_assert( from != to, "cannot transfer to self" );    eosio_assert( is_account( to ), "to account does not exist");    auto sym = quantity.symbol.name();stats statstable( _self, sym );    const auto& st = statstable.get( sym );    require_recipient( from );    require_recipient( to );    eosio_assert( quantity.is_valid(), "invalid quantity" );    eosio_assert( quantity.amount > 0, "must transfer positive quantity" );    eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" );    eosio_assert( memo.size() <= 256, "memo has more than 256 bytes" );    auto payer = has_auth( to ) ? to : from;    sub_balance( from, quantity );    add_balance( to, quantity, payer );}

                  2.防御方法

                  使用require_auth( from )校驗(yàn)資產(chǎn)轉(zhuǎn)出賬戶(hù)與調(diào)用賬戶(hù)是否一致。

                  3.真實(shí)案例

                  暫無(wú)

                  apply 校驗(yàn)

                  在處理合約調(diào)用時(shí),應(yīng)確保每個(gè) action 與 code 均滿足關(guān)聯(lián)要求。

                  1.漏洞示例

                  存在缺陷的代碼:

                  // extend from EOSIO_ABI#define EOSIO_ABI_EX( TYPE, MEMBERS ) \extern "C" { \   void apply( uint64_t receiver, uint64_t code, uint64_t action ) { \      auto self = receiver; \      if( action == N(onerror)) { \         /* onerror is only valid if it is for the "eosio" code account and authorized by "eosio"'s "active permission */ \         eosio_assert(code == N(eosio), "onerror action's are only valid from the \"eosio\" system account"); \} \      if( code == self || code == N(eosio.token) || action == N(onerror) ) { \TYPE thiscontract( self ); \         switch( action ) { \            EOSIO_API( TYPE, MEMBERS ) \} \         /* does not allow destructor of thiscontract to run: eosio_exit(0); */ \} \} \}EOSIO_ABI_EX(eosio::charity, (hi)(transfer))

                  2.防御方法

                  使用

                  if( ((code == self  && action != N(transfer) ) || (code == N(eosio.token) && action == N(transfer)) || action == N(onerror)) ) { }

                  綁定每個(gè)關(guān)鍵 action 與 code 是否滿足要求,避免異常調(diào)用。

                  3.真實(shí)案例

                  EOSBet 黑客攻擊事件復(fù)盤(pán)

                  (https://medium.com/@eosbetcasino/eosbet-黑客攻擊事件復(fù)盤(pán)-13663d8f3f1)

                  參考文獻(xiàn)

                  • 保管好私鑰就安全了嗎?注意隱藏在EOS DAPP中的安全隱患

                    https://zhuanlan.zhihu.com/p/40625180

                  • 漏洞詳解|惡意 EOS 合約存在吞噬用戶(hù) RAM 的安全風(fēng)

                    https://zhuanlan.zhihu.com/p/40469719

                  • How EOSBET attacked by aabbccddeefg

                    https://www.reddit.com/r/eos/comments/9fpcik/how_eosbet_attacked_by_aabbccddeefg/

                  • BET被黑客攻擊始末,實(shí)錘還原作案現(xiàn)場(chǎng)和攻擊手段

                    https://github.com/ganjingcun/bet-death-causes/blob/master/README.md

                  • 累計(jì)薅走數(shù)百萬(wàn),EOS Dapps已成黑客提款機(jī)?

                    https://mp.weixin.qq.com/s/74ggygC3nbDihLkobXOW2w

                  致謝

                  • 麒麟工作組

                  • eosiofans

                  • 荊凱(EOS42)

                  • 星魂

                  • 島娘

                  • 趙余(EOSLaoMao)

                  • 字符

                  合約 漏洞 智能 安全 https
                  分享到:

                  1.TMT觀察網(wǎng)遵循行業(yè)規(guī)范,任何轉(zhuǎn)載的稿件都會(huì)明確標(biāo)注作者和來(lái)源;
                  2.TMT觀察網(wǎng)的原創(chuàng)文章,請(qǐng)轉(zhuǎn)載時(shí)務(wù)必注明文章作者和"來(lái)源:TMT觀察網(wǎng)",不尊重原創(chuàng)的行為T(mén)MT觀察網(wǎng)或?qū)⒆肪控?zé)任;
                  3.作者投稿可能會(huì)經(jīng)TMT觀察網(wǎng)編輯修改或補(bǔ)充。