【警惕】首个区块链token的自动化薅羊毛攻击分析

颁布功夫 2018-07-19
一、事务介绍

近期,宝运莱官方网站ADLab结合电子科技大学的陈厅副教授【1】追踪到了以太坊token中的首个自动化薅羊毛攻击事务。被攻击的合约地址为0x86c8bf8532aa2601151c9dbbf4e4c4804e042571【2】,token名称为Simoleon (SIM),截止目前有靠近57万账户持有该合约的token:


宝运莱·(中国区)最新官方网站


经过深刻分析,我们发现攻击者对以太坊的理解极度深刻,其通过部署攻击合约获得了超过700万的token,从57万账户中脱颖而出,一举成为该合约token的第四大持有者:


宝运莱·(中国区)最新官方网站


二、被攻击的合约Simoleon


在token刊行过程中,为增长人气刊行方可能会选择空投,即在一按功夫窗口和投放总量的前提下免费给参加地址发送肯定数量的token。Simoleon合约也参与了空投能力,在总量发放完之前,任何未接受过该token空投的账户都能够挪用本合约的transfer函数给指定账户地址免费转账token:


宝运莱·(中国区)最新官方网站


三、攻击过程分析


我们分析攻击账户的token起源,通过etherscan查看该账户的token买卖纪录,一共分为两项:709万和1万,别离来自分歧的账户地址:


宝运莱·(中国区)最新官方网站


持续跟踪709万token的买卖纪录,其起源有三项:550万,155万和3万,都来自统一个账户地址0x73fa30b609249166fa425f34b7142591c92b5548:


宝运莱·(中国区)最新官方网站


分析发现地址0x73fa30b609249166fa425f34b7142591c92b5548是一个关源智能合约,由账户0x0075fd99426911b2e9650114bedc1195ad027f21创建,该合约总共有23笔买卖:


宝运莱·(中国区)最新官方网站


Simoleon合约对已经发放token的地址都进行了纪录,因而每个地址只能免费获得1万的token。要获得更多的数量,就必要创建好多新账户,而后利用这些新账户挪用Simoleon合约的transfer函数给指定账户来获得大量token。若是通过创建EOA账户来进薪ǘ羊毛,则每个账户都必要一些以太币,不然EOA账户就没有gas去挪用Simoleon合约的transfer函数,也就无法薅羊毛。显然,给大量EOA账户发送以太币会增长额表的买卖手续费。


攻击者在这里选取了一种精妙的攻击手法:首先部署一个恶意的攻击合约,地址为0x73fa30b609249166fa425f34b7142591c92b5548 ;而后挪用攻击合约中署名为0x2b6cab44的函数来动态天生一时合约 ;最后一时合约在机关函数中直接挪用Simoleon合约的transfer函数给攻击合约发送token。由于动态天生的一时合约都是未领取过token的账户,所以都能自动获得空投份额。攻击者只必要给攻击账户发送以太币就有足够的gas挪用攻击合约,同时攻击者还能节造一时合约的天生数量。


宝运莱·(中国区)最新官方网站


通过度析攻击合约的23个买卖数据,得到攻击者对0x2b6cab44函数的挪用过程如下:


宝运莱·(中国区)最新官方网站


其中第一笔的买卖(0x7f87268e06b76644ad4b8e162fb76d1c6e2e0480029b14db0e013f7d7d195e2f)细节如下,攻击者通过0x2b6cab44函数的参数来节造只天生2个一时合约,2个一时合约别离获取1万的token,而后发送给攻击合约。一时合约最后还进行了自动销毁,使自己的代码从区块链上隐没。


宝运莱·(中国区)最新官方网站


攻击者前面4笔的买卖中,每次天生的一时合约数量越来越大。其中第4次天生了80个一时合约,但是执行失败了,查看原因是gas不及。


宝运莱·(中国区)最新官方网站


攻击者在后续的买卖中,每次都选择只天生50个一时合约。理论上攻击者能够增大允许的gas亏损量,从而一次性创建80个一时合约来加快薅羊毛,但攻击者却选择一次50个的搬砖模式。通过深刻分析,我们发现攻击者对以太坊的底层机造相当熟悉,好比这里的gas亏损问题。


在以太坊中,每一笔买卖城市亏损肯定量的gas,现实亏损量由买卖的复杂度决定,但不会超过发送者指定该买卖能允许的最大亏损量。逆向分析0x2b6cab44函数后发现它是在循环创建一时合约,显然循环次数越多,这个函数挪用的买卖复杂度就越高,现实的gas亏损量就越大,允许的gas亏损量也就必须设置为越大。一时合约数量设置为50的时辰,gas现实亏损量为3096224 ;一时合约数量设置为80时,gas现实亏损量为6174290。


然而,每个区块又有最大gas亏损量的阈值,并且每个区块至少要包容1笔买卖,因而以太坊链上任何一笔买卖的gas亏损量都不允许超过区块的阈值。这进一步导致,在矿工最优化收益规划中,若是一个买卖允许的gas亏损量过大,就会偏差性把这个买卖排除在区块表,从而导致该买卖失败。攻击者通过探测尝试找到最佳一时合约数量为50(由于80个一时合约的gas亏损已经超过允许的gas亏损导致买卖失败),从而实现一次挪用能够薅更多token,同时又不会触发gas问题。


内行一出手,就知有没有!不愧是有知识的攻击者。


四、暗藏玄机的etherscan

在追踪分析过程中,我们发现了另表一路问题,即etherscan对token的变动纪录是不正确的,甚至可能齐满是谬误的。如下是攻击合约的第一笔token收入,2个一时合约总共获得2万token,而后发送给了攻击合约:


宝运莱·(中国区)最新官方网站


紧接着攻击合约产生了第一笔token支出,发送了3万token给攻击者:


宝运莱·(中国区)最新官方网站


凭据etherscan中的买卖纪录,攻击合约的收入只有2万,了局支持了3万。多支出的1万出自哪里,是否凭空产生 ?为何这1万的变动,etherscan没有任何纪录 ?


经过度析,找到原因就在Simoleon合约的transfer函数,合约在空投的时辰也会对指标地址进行免费发送token,但是这个发放却没有挪用Transfer事务:


宝运莱·(中国区)最新官方网站


因而,攻击合约的token变动过程如下:


(1)攻击合约被创建,token为零。

(2)攻击合约0x2b6cab44函数第一次被挪用,创建2个一时合约:

a)第1个一时合约初始化时挪用Simoleon的transfer函数,该函数首先给一时合约空投initialize(msg.sender),此时一时合约的token为1万 ;而后给攻击合约空投initialize(_to),此时攻击合约的token为1万 ;最后把一时合约的1万token发送给攻击合约,同时挪用事务Transfer纪录一时合约给攻击合约的发送量为1万。至此,攻击合约的token总计为2万,由空投的1万加上一时合约发送的1万组成。

b)第2个一时合约初始化时挪用Simoleon的transfer函数,该函数首先给一时合约空投initialize(msg.sender),此时一时合约占有的token为1万 ;而后把一时合约的1万token发送给攻击合约,同时挪用事务Transfer纪录一时合约给攻击合约的发送量为1万。至此,攻击合约的token总计为3万,由先前2万加一时合约发送的1万组成。

(3)攻击者从攻击合约提取全数token,提取总量token为3万。

因而,从攻击合约账户自身的出入平衡来看,并没有凭空产生token,只是etherscan未能监控到攻击合约由于空投获得的1万token。这说了然etherscan对token变动的监控是基于Transfer事务,而不是基于每个账户的现实token变动。这会带来一些潜在的威胁,由于Transfer事务在性质上只是一个路德约束,EVM自身对其没有任何限度能力,攻击者能够不挪用事务,也能够肆意批改该事务的参数,实现诸如:现实转移的token量比事务通知的数量不匹配。对于频仍买卖token的节点来说,这是一个新的挑战,由于该节点将难以通过链上数据追踪每笔token的起源,由于Transfer事务不再是正确的。

五、总结


Simoleon合约能被自动化的薅羊毛,最底子的原因在于其合约代码的空投嘉奖函数没有任何权限节造,肆意未领过空投的账户都能够直接挪用Simoleon合约来获取。因而,攻击者能够利用攻击合约来创建大量账户来领取。一种缓解法子是给空投嘉奖函数设置权限节造,好比只有合约创建者能力给指标地址发放token。


区块链的个性决定了合约代码已经部署就无法批改,无论是合约的开发者,还是投资者,还是买卖平台,都该当对合约进行多沉安全审计,尽量在上链前解除安全风险。

参考链接:

【1】Ting Chen, University of Electronic Science and Technology of China.

 http://faculty. uestc.edu.cn/chenting/zh_CN/ index.htm

【2】Simoleon (SIM).

https://etherscan.io/address/0x86c8bf8532aa2601151c9dbbf4e4c4804 e042571