EOS智能合约最佳安全开发指南

栏目: 编程工具 · 发布时间: 6年前

内容简介:1.  数值溢出1.1 漏洞示例1.2 防御方法

目录

  • 安全准则

  • 已知漏洞

1.  数值溢出

1.1 漏洞示例

1.2 防御方法

1.3 真实案例

2. 权限校验

2.1 漏洞示例

2.2 防御方法

2.3 真实案例

3. apply 校验

3.1 漏洞示例

3.2 防御方法

3.3 真实案例

  • 参考文献

  • 致谢

安全准则

EOS 处于早期阶段并且有很强的实验性质。因此,随着新的 bug 和安全漏洞被发现,新的功能不断被开发出来,其面临的安全威胁也是不断变化的。这篇文章对于开发人员编写安全的智能合约来说只是个开始。

开发智能合约需要一个全新的工程思维,它不同于我们以往项目的开发。因为它犯错的代价是巨大的,很难像中心化类型的软件那样,打上补丁就可以弥补损失。就像直接给硬件编程或金融服务类软件开发,相比于 Web 开发和移动开发都有更大的挑战。因此,仅仅防范已知的漏洞是不够的,还需要学习新的开发理念:

  • 对可能的错误有所准备

任何有意义的智能合约或多或少都存在错误,因此你的代码必须能够正确的处理出现的 bug 和漏洞。需始终保证以下规则:

1.当智能合约出现错误时,停止合约;

2.管理账户的资金风险,如限制(转账)速率、最大(转账)额度;

3.有效的途径来进行 bug 修复和功能提升。

  • 谨慎发布智能合约

尽量在正式发布智能合约之前发现并修复可能的 bug。

1.对智能合约进行彻底的测试,并在任何新的攻击手法被发现后及时的测试(包括已经发布的合约)

2.从 alpha 版本在麒麟测试网(CryptoKylin-Testnet)上发布开始便邀请专业安全审计机构进行审计,并提供漏洞赏金计划(Bug Bounty)

3.阶段性发布,每个阶段都提供足够的测试

  • 保持智能合约的简洁

复杂会增加出错的风险。

1.确保智能合约逻辑简洁;

2.确保合约和函数模块化;

3.使用已经被广泛使用的合约或工具(比如,不要自己写一个随机数生成器);

4.条件允许的话,清晰明了比性能更重要;

5.只在你系统的去中心化部分使用区块链。

  • 保持更新

通过公开资源来确保获取到最新的安全进展。

1.在任何新的漏洞被发现时检查你的智能合约;

2.尽可能快的将使用到的库或者 工具 更新到最新;

3.使用最新的安全技术。

  • 清楚区块链的特性

尽管你先前所拥有的编程经验同样适用于智能合约开发,但这里仍然有些陷阱你需要留意:

require_recipient(account_name name) 可触发通知,调用name合约中的同名函数,官方文档

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

已知漏洞

数值溢出

在进行算术运算时,未进行边界检查可能导致数值上下溢,引起智能合约用户资产受损。

1.漏洞示例

存在缺陷的代码:batchTransfer 批量转账

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 结构体进行运算,而不是把 balance 提取出来进行运算。

3.真实案例

【EOS Fomo3D你千万别玩】狼人杀遭到溢出攻击, 已经凉凉(https://bihu.com/article/995093)

权限校验

在进行相关操作时,应严格判断函数入参和实际调用者是否一致,使用require_auth进行校验。

1.漏洞示例

存在缺陷的代码:transfer 转账

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 )校验资产转出账户与调用账户是否一致。

3.真实案例

暂无

apply 校验

在处理合约调用时,应确保每个 action 与 code 均满足关联要求。

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)) ) { }

绑定每个关键 action 与 code 是否满足要求,避免异常调用。

3.真实案例

EOSBet 黑客攻击事件复盘

(https://medium.com/@eosbetcasino/eosbet-黑客攻击事件复盘-13663d8f3f1)

参考文献

  • 保管好私钥就安全了吗?注意隐藏在EOS DAPP中的安全隐患

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

  • 漏洞详解|恶意 EOS 合约存在吞噬用户 RAM 的安全风

    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被黑客攻击始末,实锤还原作案现场和攻击手段

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

  • 累计薅走数百万,EOS Dapps已成黑客提款机?

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

致谢

  • 麒麟工作组

  • eosiofans

  • 荆凯(EOS42)

  • 星魂

  • 岛娘

  • 赵余(EOSLaoMao)

  • 字符


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Agile Web Development with Rails 4

Agile Web Development with Rails 4

Sam Ruby、Dave Thomas、David Heinemeier Hansson / Pragmatic Bookshelf / 2013-10-11 / USD 43.95

Ruby on Rails helps you produce high-quality, beautiful-looking web applications quickly. You concentrate on creating the application, and Rails takes care of the details. Tens of thousands of deve......一起来看看 《Agile Web Development with Rails 4》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码