黑马程序员技术交流社区

标题: 【上海校区】EOS合约吞噬用户RAM回放分析及实践 [打印本页]

作者: 不二晨    时间: 2018-10-26 09:20
标题: 【上海校区】EOS合约吞噬用户RAM回放分析及实践
这几天,有两个朋友问到我“Cannot charge RAM to other accounts during notify”这个错误提示,我才想起原来曾经还存在过这个问题,也许是前段时间的Bancor和“假EOS”漏洞等事件影响力太大,导致很多开发人员忽略了这个RAM更新。于是,我翻了翻笔记,重新整理了下跟大家一起分享,也算是做个记录。



合约吞噬用户RAM原理分析



    这个bug的核心是require_receipt函数。目前eosio.token智能合约的转账函数transfer会调用require_receipt(to), 当to账号是一个智能合约时就会调用to的智能合约transfer方法。也就是说用户在调用系统合约(安全的代码)转账EOS的时候竟然可能会执行另外一段代码(可能是恶意代码),这段恶意代码还能得到from用户的授权,这可太危险了。这里有两个风险。

    1)如果恶意代码再调用其他合约,比如执行inline action 转账EOS给其他账号,具体金额恶意代码可以任意填写。当然,事实上这个风险肯定是已经被堵上,这个就是大名鼎鼎的eosio.code权限。恶意代码要以from的授权再执行eosio.token这个其他合约,必须得到from账号的eosio.code权限。

    2)恶意代码没法调用其他合约,那就只能在自己的合约里干事。但是在自己合约能干的有价值的事就只剩下ram,使用from的ram在本合约table创建大量数据。



哪些用户容易中招



      到了这里,你可能会说,恰好转账到恶意合约账号的机会还是很少的。实事上确实如此,但是有些群体是很容易中招的,比如交易所和空投方。

    交易所:

        恶意合约用户可以主动从交易所提取EOS到恶意合约账号,这实际上会发起一个EOS转账,自然就会让交易所账号执行恶意代码,然后恶意代码消耗多少RAM就看交易所账号的RAM量了。由于一次交易的执行时间是有限的,因而一次转账消耗的RAM也是有限的,但是由于交易所的EOS转出操作零手续费或者很低的手续费,作恶者就可以重复执行转出操作来消耗大量RAM,所以交易所是中招大户。



    空投方:

        由于代币空投方一般会空投代币到所有账号,或者活跃账号,这样空投账号就很容易转账到恶意合约账号,自然也就中招了,然后还浑然不觉。



Bug修复方法



    很显而易见的方案就是不允许在require_receipt引发的合约代码中消耗其他账号的RAM,具体代码如下:





有了这个补丁后,如果再偷RAM就会如下的错误。





正规智能合约如何适配这个改动



    很多游戏或者代币交换合约都是通过require_receipt来监控EOS转账行为然后修改合约里的table数据做记录或者换币, 也就说是这一过程消耗RAM产品正常的需求。那上面改动后,这个消耗RAM的问题怎么解决呢?智能合约买单, 即将消耗RAM的payer从用户改为智能合约,比如下图





     如果是一个EOS兑换代币的合约,最后一般是调用add_balance分发代币:





漏洞及Require_Receipt实操源码



https://github.com/itleaks/eos-contract/tree/master/stealram-exp
---------------------
【转载】
作者:ITleaks
原文:https://blog.csdn.net/ITleaks/article/details/82876742



作者: 不二晨    时间: 2018-10-31 14:46

作者: 魔都黑马少年梦    时间: 2018-11-15 16:54





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2