Written by WeaponX@零时科技
本文所有过程均在本地测试节点完成
文章用到的所有代码均在 https://github.com/NoneAge/EOS_dApp_Security_Incident_Analysis
0x00 背景
EOSBet在2018年9月14日遭到黑客攻击,根据EOSBet官方通告,此次攻击共被盗44,427.4302 EOS(折合人民币160万,9月14日价格)。
0x01 技术分析
由于EOSBet代码并未开源,但官方复盘攻击事件后给出了EOSIO_ABI
通过官方给出的EOSIO_ABI,问题主要出在以下代码
该合约对action进行转发的时候仅仅验证了code == self(调用者必须是该合约本身,即eosbetdice11)和code == N(eosio.token)(调用者必须是eosio.token)。从这里看似乎是验证了只有合约本身和eosio.token可以调用合约函数。
但是,开发者忽略了这一点。如果A合约直接向B合约发起一个transaction调用B合约的函数,那么本质上是B合约自身完成函数调用,也就是说任何合约都可以调用eosbetdice11合约中abi暴露的函数。
黑客可以直接调用eosbetdice11合约中的transfer函数,即不用消耗任何EOS来玩EOSBet,输了不赔赢了稳赚。
0x02 攻击复盘
创建eosio.token账户
部署eosio.token合约并初始化
创建游戏账户、开奖账户和攻击者账户
设置账户随机权限和开奖权限
向相关账户冲入代币
部署游戏合约并初始化
模拟黑客攻击(伪造转账通知)
查询游戏订单
可见,游戏订单已经生成,查询attacker和eosbetdice11账户
按照游戏规则,只有在支付了EOS后才能生成游戏,但是被黑客攻击后生成订单并没有消耗任何的EOS。
最后对该订单进行开奖。
总结,黑客伪造转账通知来玩游戏不消耗任何EOS,游戏成功即可获利,即使最后游戏失败也不会有任何损失。
0x03 后记
EOSBet随后将修复方案公开
可以看到,EOSBet官方给出的修复方案是仅有eosio.token合约可以调用transfer函数。官方修复后将代码开源到Gitlab,地址为https://gitlab.com/EOSBetCasino/eosbetdice_public,但是在整整一个月后又遭到了转账通知伪造攻击。欲知详情,请听下回分解:D
0x04 修复方案
零时科技安全专家建议,要防止转账通知伪造必须在处理转账交易时要验证以下内容:
通知是否来自eosio.token,即只处理eosio.token发送的通知
转账发起人或者接受人是否是自己,即转账必须跟合约本身有关,不处理其他合约的转账通知
0x05 Refer
https://medium.com/@eosbetcasino/eosbet-transfer-hack-statement-31a3be4f5dcf