God.Game智能合约攻击事务分析

颁布功夫 2018-08-24
 8月19日,,,,,,,,God.Game在以太坊区块链上部署了自己的智能合约(地址位于https://etherscan.io/token/0xca6378fcdf24ef34b4062dda9f1862ea59bafd4d,,,,,,,,简称God合约),,,,,,,,时隔一天攻击者就盗取了该合约的243个以太币,,,,,,,,价值超过6万美元。。 。 。。。8827太阳集团ADLab在监控到该事务后,,,,,,,,对该攻击进行了具体的分析和沉现。。 。 。。。


一、攻击回溯


        通过etherscan能够看到攻击者的以太币提取买卖:

8827太阳集团(Macau)股份有限公司-Official website

        买卖详情如下,,,,,,,,即攻击者0xc30e89db73798e4cb3b204be0a4c735c453e5c74(简称攻击者1)挪用了God合约的withdraw函数进行提币:

8827太阳集团(Macau)股份有限公司-Official website


        查看攻击者1在God合约中是否持有token,,,,,,,,靠近20万的数量。。 。 。。。

8827太阳集团(Macau)股份有限公司-Official website

        查看攻击者1在withdraw挪用之前对God合约的挪用,,,,,,,,如下:

8827太阳集团(Macau)股份有限公司-Official website

        从攻击者1的买卖来看,,,,,,,,它发往God合约的最早买卖是sell挪用,,,,,,,,注明在sell之前它就已经有了God合约的token。。 。 。。。那么攻击合约在此之前,,,,,,,,注定有其它账户给它转移过token。。 。 。。。不然,,,,,,,,它不会有能够sell的token。。 。 。。。

        在追踪攻击者1的token变动过程中,,,,,,,,我们发现另表一个攻击者(简称攻击者2,,,,,,,,地址为0x2368beb43da49c4323e47399033f5166b5023cda),,,,,,,,它挪用了一个攻击合约(地址为0x7f325efc3521088a225de98f82e6dd7d4d2d02f8)给攻击者1转移了20万token:

8827太阳集团(Macau)股份有限公司-Official website


        攻击者2挪用攻击合约的transfer函数,,,,,,,,指标地址为攻击者1,,,,,,,,数量为20万。。 。 。。。由于攻击合约并没有盛开源码,,,,,,,,因而这里的transfer函数仅仅是函数署名匹配的了局(有肯定几率是其它名字)。。 。 。。。那么,,,,,,,,攻击合约的20万token是从哪里得到的? ??? ? ??


        持续跟踪攻击者2和攻击合约,,,,,,,,发现攻击合约是由攻击者2创建的,,,,,,,,且攻击者2对攻击合约的挪用就是在God合约被攻击提现的功夫窗口钟祝。 。 。。。

8827太阳集团(Macau)股份有限公司-Official website


        从攻击者2的买卖行为,,,,,,,,能够看出他先给攻击合约转入4.3 token,,,,,,,,而后从攻击合约转出4.3 token。。 。 。。。此时,,,,,,,,攻击合约的token为0。。 。 。。。随后,,,,,,,,攻击合约直接转20万token给攻击者1(还转移了21万给另表一个地址),,,,,,,,这批注攻击者在挪用reinvest函数时应该使攻击合约的token产生了某种变动。。 。 。。。


        接着分析这个reinvest买卖,,,,,,,,它是直接挪用不开源的攻击合约,,,,,,,,其内部机造我们并不明显。。 。 。。。但是,,,,,,,,这个买卖过程会触发God合约的两个事务,,,,,,,,onTokenPurchase和onReinvestment:

8827太阳集团(Macau)股份有限公司-Official website


        通过这个事务的纪录数据,,,,,,,,能够看到该reinvest挪用使得合约判定采办token的以太代币数量为一个大数,,,,,,,,并且远远超出以太币刊行总量。。 。 。。。这个信息也反映出reinvest函数内部逻辑肯定产生了某种非预期的行为。。 。 。。。


        通过度析God合约源码,,,,,,,,发现onReinvestment事务仅在God合约的reinvest函数中触发:

8827太阳集团(Macau)股份有限公司-Official website


        可见,,,,,,,,onReinvestment的以太币参数的最终推算方式为:

8827太阳集团(Macau)股份有限公司-Official website


        这一行代码显著存在整数溢出的理论可能,,,,,,,,由于它没有使用SafeMath等类似安全运算操作。。 。 。。。但这里溢出的值并不是经典0xfffff…等类似的大数,,,,,,,,而是一个够大但又远不及uint256极大值的数。。 。 。。。


        仔细观察发现,,,,,,,,magnitude变量是2的64次方,,,,,,,,而后我们做一个等式变换:

8827太阳集团(Macau)股份有限公司-Official website


        这样我们就找到了经典整数溢出的第一现场指纹,,,,,,,,只必要上面减法操作的第一操作数比第二操作数略幼即可。。 。 。。。很显然,,,,,,,,第一操作数又可划分为两个子操作数的乘法,,,,,,,,只有任一个为零即导致了局为零。。 。 。。。此时,,,,,,,,第二操作数只有是肆意一个幼正数即可产生上面的经典指纹。。 。 。。。


        持续机关上述的操作数。。 。 。。。首先,,,,,,,,tokenBalanceLedger_[_customerAddress]在合约挪用的高低文中暗示挪用者持有的token。。 。 。。。因而,,,,,,,,只有挪用者不持有合约token,,,,,,,,这个值就是零。。 。 。。。此时无论profitPerShare_值为几多,,,,,,,,乘法了局都为零。。 。 。。。这样减法的第一操作数为零的前提,,,,,,,,就等闲机关出来了,,,,,,,,即挪用者不持有God合约token。。 。 。。。而后,,,,,,,,payoutsTo_是一个mapping对象,,,,,,,,合约挪用者的初始值为零,,,,,,,,必要使其为一个正数。。 。 。。。

8827太阳集团(Macau)股份有限公司-Official website


        分析God合约中批改payoutsTo_的代码有:

8827太阳集团(Macau)股份有限公司-Official website


        攻击合约在reinvest挪用之前只执行过transfer挪用和withdraw挪用。。 。 。。。其中transfer挪用从攻击合约转token到表部账户,,,,,,,,所以不会批改合约的payoutsTo_值,,,,,,,,但withdraw函数会直接批改合约的payoutsTo_值。。 。 。。。因而,,,,,,,,只有在reinvest之前挪用一次withdraw函数就能够使得减法的第二操作数为一个正数。。 。 。。。


        最后,,,,,,,,第一个操作数为零值,,,,,,,,第二个操作数为正数,,,,,,,,并且减法了局强造转换为无符号整数,,,,,,,,在没有使用安全运算库的前提下直接使用减法操作就会导致溢出,,,,,,,,了局为一个很大的正数。。 。 。。。至此,,,,,,,,攻击者的齐全攻击过程如下:


8827太阳集团(Macau)股份有限公司-Official website

二、Remix复现


        在分析了齐全攻击蹊径后,,,,,,,,我们能够机关出如下的攻击合约:

8827太阳集团(Macau)股份有限公司-Official website


        在remix中依照如下步骤进行操作:


        (1)部署God合约(为了方便追踪内部数据结构的变动,,,,,,,,直接把全数成员和函数都沉新界说为public);;;;;;


        (2)用1eth,,,,,,,,采办第一次token,,,,,,,,引用地址设置为0x00…;;;;;;

8827太阳集团(Macau)股份有限公司-Official website


        (3)再用一样的参数来采办一次(肯定要再来一次,,,,,,,,由于此时合约的profitPerShare_依然是零值,,,,,,,,这会导致withdraw挪用的函数建饰符失败);;;;;;

8827太阳集团(Macau)股份有限公司-Official website


        (4)部署攻击合约Test(传递God合约地址给Test);;;;;;


        (5)挪用God合约的Transfer给Test发送Token(这里直接把采办的全数token都发送从前);;;;;;


8827太阳集团(Macau)股份有限公司-Official website

        (6)挪用攻击合约Test的withdraw函数,,,,,,,,攻击合约的payoutsTo_已经被批改为大数;;;;;;


8827太阳集团(Macau)股份有限公司-Official website

        (7)挪用攻击合约Test的transfer函数把token全数给创建者,,,,,,,,Test此时占有的token为0,,,,,,,,payoutsTo_为大数;;;;;;

8827太阳集团(Macau)股份有限公司-Official website


        (8)挪用攻击合约的reinvest函数,,,,,,,,在日志中能够看到纪录采办token的eth为海量,,,,,,,,并且成功采办了大量token;;;;;;

8827太阳集团(Macau)股份有限公司-Official website


        (9)攻击合约Test通过溢出获得了大量token,,,,,,,,攻击者就能够从这个合约给其它地址转移token,,,,,,,,并进行售卖套取eth。。 。 。。。


三、幼结


        God合约被攻击的缝隙点比力单一,,,,,,,,即尺度的整数溢出。。 。 。。。它的复杂在于整数溢出的利用有多个约束前提,,,,,,,,并且是在分歧的业务逻辑中:


        (1)在溢出攻击的业务逻辑中,,,,,,,,攻击者必须没有God的token,,,,,,,,且payoutsTo_值必须为正数;;;;;;


        (2)要使payoutsTo_为正数,,,,,,,,攻击者就必须在其它业务逻辑中批改,,,,,,,,好比withdraw;;;;;;


        (3)要执行withdraw,,,,,,,,攻击者就必须持有God的token(最终溢出时又不能持有token)。。 。 。。。


        因而,,,,,,,,攻击者必要通过屡次触发God合约的分歧业务逻辑能力最终造成整数溢出。。 。 。。。


        God合约的代码编写存在多处缺点:


        (1)给治理员留下肆意地址的token操控能力,,,,,,,,并且操控不触发事务。。 。 。。。这意味着批改是悄无声息的,,,,,,,,除非有人去轮询监控每个地址的token变动;;;;;;


        (2)Token的某些转移过程没有挪用尺度ERC20事务接口,,,,,,,,导致etherscan上看到的token变动是极端不正确的,,,,,,,,不利于公开通明监督;;;;;;


        (3)代码中不思考限度循环,,,,,,,,无意思的gas浪费(这也导致了在Remix调试中时时崩溃);;;;;;


        (4)合约中的业务逻辑没有注明规范,,,,,,,,仅盛开合约代码并不能等价于项目通明。。 。 。。。