加密貨幣交易所 加密貨幣交易所
Ctrl+D 加密貨幣交易所
ads

Uniswap重入事件詳盡解析_ETH:Louie Duck Token

Author:

Time:1900/1/1 0:00:00

去中心化金融(DeFi)作為區塊鏈生態當紅項目形態,其安全尤為重要。從去年至今,發生了幾十起安全事件

BlockSec獨立發現了多起DeFi安全事件,研究成果發布在頂級安全會議中(包括USENIXSecurity,CCS和Blackhat)。在接下來的一段時間里,我們將系統性分析DeFi安全事件,剖析安全事件背后的根本原因

如果能重來,你會做什么?

本期簡述了一個意外發現時空暗道的毛賊,如何戲弄守護在秘寶洞口的獨角獸,將財寶竊于囊中的魔幻故事

閱讀建議:

如果您初識Defi,又有耐心的話,可以從頭開始閱讀,酌情跳過廢話

如果您對AMM、ERC777、Uniswap等非常了解,可以直接從0x1中Uniswap重入部分開始

文章較長,看不下去,記得點個關注再走喔~

正文

時間:2020-4-18.8:58.#9893295

imBTC是tokenLon發行的與BTC價值1:1錨定的ERC777標準代幣

相關代幣的價值情況:

imBTC($7029.38):ETH($178.81)=39.31

背景介紹

AMM

交易(Trade)是什么:

交易就是賣家和買家,倆人你情我愿,大家都覺得不虧,可以達成這次的交換

交易所(Exchange)是什么:

交易所是這個游戲的組織者,它就像一個紅娘,男男女女來到她這里,提出自己的要求,它便開始牽線,還要保證雙方都滿意

放在現實中,這些要求,就是買家賣家的出價,這些全都記錄在交易所的服務器中。服務器中,買賣的交易請求不斷更新跳動,交易所的機器要做的就是在尚未達成請求中,找到一對可以匹配的,然后促成這筆交易。比如:張三想不低于50塊賣茅臺的股票,李四想不超過60塊買茅臺的股票,機器看到后「剛好,那你倆就湊合過吧」。這種便是中心化交易所通過記賬簿的交易處理方式

但是,這有什么弊端呢?對于健康運行的交易所,市場很熱,不斷有大量的買單和賣單,機器很快就可以找到匹配的交易對。如果對于低迷的市場,你想賣,但是沒人買,這會發生什么?找不到接盤的人!這很影響效率,所以這時市場上出現了做市商

什么是做市商(MarketMaker)呢?

剛才提到,買家找不到賣家,或者賣家找不到買家。怎么解決這一問題呢?

中間商!無論是買家還是賣家,都可以直接找他,他會大量回購資產,再賣出。這其實類似于一種緩存的機制。他要求做市商必須有足夠的資金,大家才相信他不會亂要價

去中心化交易所是什么?

DEX無非就是將上述的過程放到區塊鏈上。它可以直接把上面的程序改寫成智能合約照搬到一條區塊鏈上,同樣用這種記賬簿的方式去撮合交易。但是要知道區塊鏈上的存儲是相當昂貴的

于是人們就開始尋找一種方案,可以通過智能合約實現代幣的有效交換,什么叫有效交換呢,就是無論的買的人還是賣的人都覺得不虧

既然問題出在,記賬簿方式一方面可能存在找不到匹配對手,另一方面鏈上存儲比較昂貴。那我們可不可以把做市商這一機制也搬到鏈上來?簡單來說,就是有一段智能合約它可以吸收大量的資金,每當有人想交換代幣時,直接調用這個合約就可以以市場價獲取另一種代幣,這就是自動化做市商

自動化做市商是什么:

上面提到AMM需要解決兩個問題:

1)如何吸收大量的資金?

傳統做市商需要先買資產,但是如果AMM先去買幣,它去哪里買呢?記賬簿類型的DEX嗎?這并沒有解決根本矛盾。

鏈上混的,大家誰沒幾個幣,所以它只要騙大家過來把幣放在自己這里,資金不就來了。

不過如果沒有經濟激勵,沒人會愿意將自己的錢放在別人口袋里的。這個激勵便是從交易的手續費中獲取,當AMM運作起來,只要有人做交易,就需要交一定的手續費,這個手續費會分配給那些給池子提供流動性的人

Bitwise推出DeFi指數基金 支持UNI AAVE等代幣:加密資產管理公司Bitwise今日宣布,已推出首只DeFi指數基金:Bitwise DeFi加密基金,該基金為合格投資者提供對DeFi代幣的敞口。該基金啟動時只有少量種子資產,每周兩次認購,該基金最初將包括Uniswap、Aave、Synthetix、Maker、 Compound、 UMA、Yearn.Finance、0x和Loopring。(TheBlock)[2021/2/17 17:24:50]

2)如何以市場價交易?

現在DEX把大家的幣都騙過來了,這時有人來了,想用一種代幣來買走池中的另一種代幣。他能買多少呢?

其實抽象來看,每個人擁有的數字貨幣不過是區塊鏈上存的數字,而不同的代幣就是不同的變元。交易這一過程,對于交易池來說,就是一個變元增加,另一個變元減少

回憶一下我們小學學到的數學知識:一條曲線的斜率k=Δy/Δx,上面能買多少的問題,就變成了如何找到和市場一致的這個k

對于上面這條曲線,曲線上的每一點,就代表交易池中兩種代幣的一種狀態,比如P點:y代幣有B個,x代幣有A個。這時有人來池中做交易他花了BD個y可以換出AC個x,這時交易池的狀態就從P點轉移到了Q點,斜率?k值隨之"變小"

因為這個曲線是無限延展的,k值可以取遍0-∞,所以肯定存在一個點與市場的狀態一致(斜率k相等)

那問題來了,誰來推動當前的交易池狀態向著市場狀態逼近?

答案是套利者,每當交易池中狀態與市場狀態不一致時,就會有套利者發現機會,比如當前池中1ETH:5USDT,市場上1ETH:10USDT,這時明顯交易池中ETH的價格虛低,就會有人來交易池中用5個USDT買走1個ETH,再去市場上賣掉獲得10個USDT,凈賺5個USDT,而此時交易池的狀態就向市場的狀態趨近了一步,就這樣不停的有人做套利,最終交易池的狀態一定會和市場的狀態相差無幾

總結

AMM類型的交易所解決的痛點是:區塊鏈上代幣的有效交換

俗話說的好:「哪里有痛點,哪里就有錢賺」。有很多人愿意掏錢來使用代幣交換這個服務

AMM一方面用這些手續費吸引玩家向資金池投錢,資金池有了錢就可以通過AMM實現代幣交換;另一方面,由于套利者的存在,池子代幣交換的價格與市場價格一致

這樣,提供流動性的玩家賺到了手續費,套利者賺到了差價,用戶得到了代幣有效交換這一服務。三個角色缺一不可,構成這一系統。一拍即合,各自歡喜

其中AMM有幾種性質,最廣為人知的就是:交易池中底層代幣(UnderlyingToken)的儲備量滿足一定的不變式,比如Uniswap的恒定乘積(reserve0*reserve1=k)

但其實還有很多隱藏的性質?(伏筆1),想知道嗎?哎,我就不說,想知道就自己繼續看下去!

ERC777

提出時間:2017-11-20

我們都知道ERC20中代幣轉賬函數的基礎款是?transfer,它的功能只是簡單的balance加減,比如alice調用?transfer(bob,100)?,bob是不知道誰給自己轉了100個token

當然對于我們來說,可以通過查看Ethscan或者查找區塊數據得知。如果bob是一個合約,他是沒辦法在轉賬?balance+=100;?發生的當下得知。這產生了諸多不便,比如用戶想使用合約的一項服務,但是支付了服務費后,合約并不知道誰付錢給了它

因此ERC20中同時存在另一套組合技?approve?+?transferFrom,這樣用戶就可以通過先授權給第三方,第三方再通過查看?allowance來代替委托人轉賬,這無疑帶來的很多的便利

有時候為了方便,同時省去每次approve的gas開銷,用戶選擇直接approve最大值?0xffff...,這種行為是不安全的,如果第三方合約受到攻擊,您的資產也會處于危險中

更多細節了解,可以關注我們的相關工作:TowardsunderstandingtheunlimitedapprovalinEthereum(https://www.youtube.com/watch?v=ijgYfdOADVI)

UNI突破15美元關口 日內漲幅為4.58%:火幣全球站數據顯示,UNI短線上漲,突破15美元關口,現報15.0032美元,日內漲幅達到4.58%,行情波動較大,請做好風險控制。[2021/1/28 14:10:09]

但是ERC20就完美了嗎?其實還沒有,其中為人所詬病有:

每次都需要先approve再進行其他操作

ERC20中的授權沒有權限的概念,只是簡單的授權余額,這在很多情況下還是存在危險的

每次轉賬無法攜帶信息,這限制了很多應用的想象力

代幣誤轉后鎖死在合約中

可以看到ERC20的功能是非常單一且基礎的,為了對此進行改進提出了ERC777標準

實現的方式無非是在ERC777標準中實現ERC20同樣的函數(如:transfer,transferFrom...),但是在這些接口內部調用ERC777的邏輯

了解了ERC777的來歷以后,我們看看具體ERC777做了哪些改進:

1.在轉賬的過程中可以攜帶數據,相當于在ERC20的transfer函數上加了一些參數,這個數據有什么用呢,作為hook函數的參數,便于hook函數據此來作出不同的決策

2.?代幣的轉移不僅僅是balance的加減:ERC777引入了兩個hook函數?tokensToSend?和?tokensReceived,這兩個函數是干什么用的呢?過程很簡單:在一筆轉賬交易過程中,balance減少的地址如果實現了?tokensToSend?接口函數,就先去執行holder的這個接口函數;同樣的,balance增加的地址如果實現了?tokensReceived?,收到轉賬后會去執行receiver的這個接口函數

這里利用的是ERC1820注冊機制:這里不需要詳細了解細節,只要知道任何地址都可以實現接口函數,對于EOA來說,可以通過部署一個合約,在其中實現接口函數,并將注冊信息發給ERC1820合約,此后當EOA觸發相關的接口時,就會先通過ERC1820查找接口實現的合約地址,再去調用相關的接口函數

值得注意的是,ERC777標準中提到,token實現應滿足?sender回調→更新狀態→receiver回調?的順序,以防止發生重入事件,代碼中的表現為:

還有一些其他的特性,如:操作員概念、Mint與Burn完善了token的生命周期等等,與本次攻擊關系不大,暫且不展開

總結

ERC777是對ERC20的"升級"

它會在代幣轉移(balance加減)之前回調TokensToSend函數,轉移之后回調TokensReceived函數

TokensToSend函數由轉移代幣的持有者(可以是合約)實現,TokensReceived由轉移代幣的接收者實現,這給了用戶很大的自由,但也帶來了一些問題,比如本次的攻擊?

攻擊分析

經典重入攻擊

我們先不急著去看攻擊過程,先復習下最簡單的重入攻擊

在這些"經典"攻擊中,攻擊者通過重入可以不斷的使合約對其轉賬,直到退出"遞歸"時才更新一次的狀態,他可能轉賬了1000個Token(50個*20次),但是balance卻只減少了50

如果攻擊者可以在transfer的過程中重新調用withdraw函數,就可以實現重入。主要原因在于:合約中轉賬等操作先于余額狀態的更新

總結

簡單來說,重入攻擊就是打斷施法,重點在于:

兩筆共計超45445枚ETH從未知地址轉移到Uniswap:Whale alert數據顯示,北京時間11月18日8:47,有20700枚ETH從0x767E開頭的未知地址轉移到Uniswap,價值約1000萬美元,交易哈希為:0x55af215d8bfb1470711c54e21a565a489b6643d0213c8c9288b2a6a3a4ecb8fc。隨后,北京時間11月18日9:10再次有24745.83枚ETH從上述未知錢包轉移到Uniswap,價值約1201萬美元,交易哈希為:0x7781c5c73572f2df16e85c80f836b090bf0032b25ab76c7a28502dd3583788fb。[2020/11/18 21:08:44]

在哪里打斷施法

打斷以后又做了些什么可以影響后續的結果

重入攻擊有一個重要的特征,就是:先轉賬,后更新狀態

對于上面這種傳統的重入攻擊,打斷的便是「轉賬+記賬」這一組合技,做的事情就是不斷重新轉賬,以影響后續的記賬結果

重入Uniswap

(前方重點!)

那Uniswap如何重入呢?我們知道,Uniswap是一個去中心化交易所,用戶可以在上面交換代幣

UniswapV1只實現了ETH和任意token之間的交換,對于token與token的交換,可以借助ETH中轉來實現

這并不像傳統重入攻擊的「轉賬+記賬」模式。那它可以在哪里打斷施法,又可以做哪些事情影響后續的結果呢?

代碼分析

Uniswap交易對合約中的交換函數,原理基本一致,即保證交易池內兩種幣數量的乘積恒定,這些函數會先調用getInputPrice方法獲取可以購買的另一種代幣數量:

對應的公式為:

這里公式表示:池中原來儲備量為?ether:token?,現在alice手里有?token(put)?個token,ether(get)?代表她能從池中買到多少個ETH

我們現在直接挑其中一個開錘,比如tokenToETH(這個函數的功能是用token換ETH):

我們可以看到這個函數先將ETH轉給用戶,再調用transferFrom收取用戶的代幣

我們是否可以打斷這兩筆轉賬呢?對于普通的ERC20代幣,確實是沒有辦法打斷轉賬的過程,但是還記得嗎?我們提到的ERC777代幣,這種復雜的代幣,恰恰提供了這樣的暗道,使不懷好意之人,有了可乘之機

現在想法很簡單了,如果Uniswap存在一個ETH-ERC777的池,我們就可以利用ERC-777的回調功能,在transferFrom的過程中,重入這個函數,繼續發送(send)一筆ETH給自己

這時可能有聰明的讀者要問了:「即使重入后又轉了一筆ETH給自己,后面"遞歸"返回后,不是還要為每輪重入所購買的ETH付相應的token嗎?」沒錯,是這樣的,如果只是簡單的重入這個函數,只是把一次購買,變成了多次購買,毛都賺不到

更聰明的讀者可能現在已經想起來,之前我們提到的?Uniswap的計價公式,由ERC-777的特點,我們可以知道重入是發生在ETH之后,token余額變更之前,這就意味著,在重入過程中計價公式的變量狀態其實是不一致的,攻擊者正是利用這一點,每次薅一點羊毛,直到把人家羊給薅禿了:

從公式中可以看到,本來在一次swap后,token和ETH的狀態會同時變化,但是由于重入發生在發送?ETH?和更新token余額之間,直接被打斷施法了,從而造成了悲劇

數據:Uniswap鎖倉量突破20億美元,位列榜首:Debank數據顯示,去中心化交易協議Uniswap鎖倉量已突破20億美元,位列榜首。Maker以16億美元鎖倉量位列第二位,SushiSwap以15億美元鎖倉量緊隨其后。

注:DeBank共統計了50個項目樣本,總鎖倉量(TVL)系通過計算所有鎖定在該項目智能合約中的ETH及各類ERC-20代幣的總價值(美元)之和而得到。[2020/9/3]

很簡單的道理:如果正常的兩次調用,第二次是token↑使得etherget?↓,但是由于重入后狀態沒有更新,所以相比"正常情況"下可以獲得更多的ETH

公式相關推導過程(基本原理就是:保證交易池中兩種代幣一直滿足恒定的乘積

可能讀到這里,你還是感覺哪里不對,這是正常的,如果有興趣,你可以思考這樣幾個問題:

1)這樣一定能獲利嗎,需要滿足什么條件嗎?

2)攻擊者獲利是最優的嗎,還可以怎樣優化?

在深入分析部分,小編對這些問題做了一些簡單的嘗試,如果有興趣,不妨繼續看下去

(這已經是小編第4次復盤這次攻擊,但還覺得很多問題沒有真正的搞清楚,所以如果你沒看懂,那也沒什么大不了的)

總結

總結來說,這次的攻擊是由于:

①UniswapV1不兼容ERC777代幣→②從而導致合約代碼可重入→③從而導致恒定乘積中變量狀態不一致→④從而導致交易池資金被薅走

RealWorld

原理大概就是這樣,管你聽沒聽懂,繼續看就完了,下面我們來看看realworld中攻擊者到底做了什么?

其實說到現在,更更聰明的讀者,都可以跑去自己攻擊了(友情提示:小心警察叔叔找上門哦

我們隨便找一筆攻擊者的Tx:0x32c83905db61047834f29385ff8ce8cb6f3d24f97e24e6101d8301619efee96e

可以看到攻擊主要分為兩個部分:

首先是一堆的自毀合約,看起來比較迷惑,但是查看這些自毀合約的調用者就可以知道這是為了節省攻擊的Gas

攻擊過程:

step1:使用1ETH向Uniswap(imBTC)換取imBTC

step2:將換得的imBTC分兩次,向Uniswap(imBTC)換回ETH,通過簡單的計算我們可以知道:0.611341052127704463+0.472375805535296596=1.0837168576630012>1?通過這種方式來薅羊毛

step3:最后將收益從攻擊合約轉給攻擊者自己)

GST(GasToken):是一個旨在節省Gas的代幣,我們知道Ethereum有一個特性就是銷毀合約時會返回大量的Gas,所以GST的原理就是:在GasPrice便宜的時候,用戶可以通過這個合約生成一系列子合約,來"存儲Gas",當需要時再用GST調用合約銷毀當時創建的子合約換取相應的Gas

:?0x0000000000b3f879cb30fe243b4dfee438691c04?(https://gastoken.io/)

Misc

這次的攻擊事件,攻擊者"或許"不是第一個發現漏洞的人

Uniswap交易對合約中的重入漏洞,早在?2019年1月12日?ConsenSys的審計報告中就被提及,而且在?#14commit?中提到:合約中可能存在多種方式的重入攻擊,并給出了簡單的攻擊過程

審計報告中提出:對于UniswapV1交易對合約中的exchange類型函數,無論transfer是發生在token余額狀態變更前,還是token余額狀態變更后,如果transfer函數可以重入,都會造成損失,并給出了后一種情況的簡單攻擊過程模擬

Yam Finance:強烈建議在16時rebase前退出Uniswap YAM/yCRV池:DeFi項目Yam Finance(YAM)在推特表示,我們正在緊急調查一個可能會阻止提案執行的潛在缺陷。我們強烈建議在UTC時間8點(北京時間16時)rebase之前退出Uniswap YAM/yCRV池。隨后官方再次發推提示:如果治理不能通過該提案,那么在rebase期間累積的yCRV將面臨無法移動的風險。

此前消息,Yam Finance(YAM)修復調倉機制bug的投票已滿足最低16萬枚代幣的委托要求。根據項目官方推特披露的數據,YAM持幣人已委托了173635枚代幣,該協議將有機會成功修改合約,進而修復bug并允許項目繼續進行。YAM官方表示,這并不等于YAM已被“拯救”,治理提案將會在北京時間下午3點到4點之間提交,所以YAM治理提案不會在下午3點之前執行。[2020/8/13]

利用ERC-777重入屬于前一種,重入發生在狀態變化前,審計報告中還指出,相比第二種情況,利用ERC-777來攻擊會更簡單

"Iftokenbalancesareupdatedafterthereentrancy(e.g.ERC-777),thealgorithmiseveneasierandrequiresfewerfundstostealliquiditypool."

https://github.com/ConsenSys/Uniswap-audit-report-2018-12#31-liquidity-pool-can-be-stolen-in-some-tokens-eg-erc-777-29

深入分析

Uniswap的過程可以簡化為:兩筆轉賬,一筆向交易池轉入,一筆從交易池轉出。有三個位置可以切入,①第一筆轉賬前,②?兩筆轉賬中間,③?第二筆轉賬后。顯然在第二筆后是沒有意義的

注意!!!要記住:用戶從Uniswap買幣時,Uniswap是先將錢轉給用戶,再將用戶的錢轉來。所以這兩筆轉賬是?先轉出,再轉入

現在,可以揭秘上面提到的AMM的隱藏性質了,那就是:

隱藏性質1:

AMM恒定乘積的曲線x*y=k,是一個"凹函數",凹函數意味著,他不像一次函數那樣,相等間距的x變化,帶來的y變化是相同的。而是:沿著一個方向,相等間距x的變化(Δx),引起y的變化(Δy?)會越來越小或越來越大!

你可能有點懵。下面我們一點點來看:

最最簡單的情況下,我們不考慮交易的手續費,在ETH/imBTC池中,用?Δy?個ETH換出?Δx?個imBTC,緊接著再用?Δx?個imBTC換回ETH可以換出多少呢?答案是?Δy,這很簡單

接著我們引入手續費,有了手續費的摩擦,這一結論就不成立了,兩次交易都會損失一部分手續費,導致最后換出的ETH

接著我們再考慮一個問題:同樣先不考慮手續費,如果我們先用2*Δy?個ETH換出?2*Δx?個imBTC,接著分兩次,每次用?Δx?個imBTC去池中換ETH,兩次換出的ETH數量相等嗎?

答案肯定是不相等的。原因就在于上面提到的凹函數這一性質!

?y軸代表ETH,?x軸代表imBTC;?從B到A代表:?先用ETH買imBTC,?再從A回到B代表:?用imBTC買回ETH

這兩次交換,第一次換出的數量要大于第二次的數量。這就意味著,總共能換出?2*Δy?個ETH,但是第一次能換出的ETH數量是大于?Δy?的!

如果能重來,那有沒有可能,用imBTC換回ETH的過程中,兩次交換都用第一次的結果?

沒錯,只要我們在第一筆轉帳前打斷施法(打斷點①),重新調用交換函數!

這樣用2x個ETH換出2y個imBTC,接著分兩次每次都可以用y個imBTC換出>x個ETH,最終換出比投入更多(>2x)的ETH(在不考慮手續費的情況下

由于Uniswap是先計算可以換出代幣的數量,再進行轉賬。這樣就可以:重復使用第一段的價格

QUIZE:不考慮手續費這是穩賺不賠的買賣,但是如果引入了手續費,事情會怎么樣呢?這就有一定的條件了,要看到底薅的更多,還是虧得更多。

>有興趣可以自行推導

對于Uniswap是否可以實現這種,在第一筆轉帳前重入呢?

很不幸的是,Uniswap的邏輯是先操作ETH再操作代幣,這意味著無論是用ETH買代幣,還是用代幣買ETH,都是先將ETH轉出給用戶,或是先將ETH轉入給交易池,這便不符合我們上面提到的第一筆轉賬需要是ERC777代幣(這樣我們才可以回調)

但是!Uniswap還存在著TokenToToken這種方式,因為V1只支持Token/ETH交易池,所以這一函數的實現原理,就是:先在第一個池中用Token換出ETH,再在第二個池中用ETH換出Token

可以看到這個函數的實現邏輯是:比如我們使用imBTC換DAI,它先將imBTC轉給第一個交易池,然后將換出的ETH轉給第二個池獲取相應的DAI

太好了,這樣不就有了ERC777代幣作為第一筆轉賬的條件了嘛!

但是,我們要怎么把錢取走呢,方法是:我們自己來創建第二個交易池,因為我們是這個交易池中代幣的owner,所以我們可以mint出無限多的代幣,來將池中的ETH拿空,而池中的ETH便是第一個我們在第一個交易池中的輸出,也就是重入攻擊的獲利?

實驗結果:?

這其實就是ConsenSys?審計報告中提出的攻擊方式(但是并未實現|回收伏筆2

隱藏性質2:

k值越小,曲線凹的程度越大,相等間距x的變化(Δx),引起y的變化(Δy?)會越來越小!?(如下圖中,ΔAC>?ΔA'C')

上面在第一個代幣轉賬前打斷我們已經驗證過是可行的了,那在兩個代幣轉賬之間打斷呢?

攻擊者采用的便是這種方式!

事實也是可行的,第一筆轉賬是從Uniswap轉出(交易池先將錢轉給用戶),交易池中一種代幣的存量增加(y?)這使得k變小,曲線由上面一條躍遷到下面那條(A→A')

從圖中可以明顯的看到A'狀態下的價雖然次與A點,但是還是優于C點的(p=y/x),所以如果不考慮手續費,繼續使用?Δx的imBTC換出的ETH:?ΔA'C'?>?ΔCB

這意味著,相比正常情況下(正常情況下:?2*ΔximBTC可以換出?ΔAC+?ΔCB=2*Δy),重入可以換出?ΔAC+?ΔA'C'>2*Δy

如果考慮手續費,情況可能就更復雜一些了,理論上還是可以獲利的(但是是否一定可以獲利呢?小編對此也沒有證明出來

總結

由于ERC777的引入使得Uniswap的轉賬過程可以被重入

Uniswapswap的過程可以分為兩部分:從交易池轉出,?向交易池轉入

我們可以從兩個地方重入:

打斷點①

通過TokenToTokenSwap函數,如果輸入Token是ERC777標準。可以利用TokensToSend回調函數實現在兩次轉賬前重入獲利(比較復雜,也就是審計報告中提到的攻擊)

打斷點②

通過TokenToEth函數,在ETH轉賬后,Token轉賬前,利用TokensToSends回調函數重入獲利

附錄

a.攻擊者是否獲利最大化,如何獲利更多?

這是一個比較困難的問題

從直覺上來看:攻擊者每筆攻擊交易重入的次數越多,使用的Ether數額越大,獲利就越多,但是還要考慮實際交易對中真實的情況

因此小編只是做一些簡單的嘗試與統計:

優化的維度有:初始時攻擊者投入的Ether數量,投入Token占比,重入的深度、攻擊次數

這些都可以在數學上求解,但是小編懶(bu)得(hui)搞,有興趣的大佬可以嘗試

實驗條件:區塊號#9893295,工具brownie

實驗1:獲利與投入ETH數量及投入Token占比的關系

實驗參數:使用ETH的數量,投入Token的占比

這里的token占比指的是:還記得凹函數這一性質嗎,前半段下降快于后半段,這里實驗的是前半段與后半段的比例對獲利的影響,其中占比指的是前半段占全部的比例

結論:投入ETH的數量越大,獲利越大,并且增長的幅度也會有所加大。投入token的占比在0.5時接近最大值

實驗2:獲利與攻擊次數的關系

實驗參數:分別使用100ETH/累計ETH兩種方式,嘗試增加攻擊次數

我們知道隨著攻擊次數的增加,池中狀態會一直向曲線的左側移動,也就是說隨著攻擊次數的增加,獲利會逐漸增大

上面兩圖是兩種不同的方式,上圖每次使用固定的100ETH進行攻擊,下圖初始用100ETH攻擊,后續每次使用的ETH會累積上之前的獲利。很顯然累積上獲利使池子更快的被掏空

結論:隨著攻擊次數的增加,獲利會以指數趨勢增加

實驗3:重入次數與獲利的關系

實驗參數:重入次數取,使用100ETH

結論:隨著重入次數的增加,理論上獲利是會更多的,但是增長的幅度逐漸趨于平緩

重入次數與token占比是關聯的,比如重入2次,token占比為0.5...

同時還需要考慮gaslimit等條件,所以攻擊者選擇重入2次,token占比0.5,還是有道理的

b.?本次事件涉及的攻擊Tx有哪些(時間范圍)??

通過使用我們的內部工具與數據集,得到結果如下:

對于Attacker(0x60f3fdb85b2f7)來說,攻擊Txs涉及的區塊范圍為:9893295-9894249?共954塊

c.?攻擊機會何時開始存在?

攻擊者是否發現的足夠早?

?UniswapV1的imBTC池在#9059910被創建出來,攻擊開始于#9893295

d.?本次事件后續結局如何?

通過使用我們的內部工具與數據集,得到結果如下:

在?#9894379?塊(2020-4-1812:49:50):0xb9e29984fe506向imBTC合約發送一筆Tx(0x7ce097c5149),調用其pause方法關停合約

pause的實現方式很簡單,利用一個全局標志變量_pause,對每個轉賬函數加一個modifier來修飾,當這個標志為true時,revert掉

在?#9895526?塊(2020-4-1816:57:55):0xb9e29984fe506向imBTC合約發送一筆Tx(0xced24b64665b9),調用unpause方法,解凍imBTC合約,恢復正常交易

安全建議

道路千萬條,安全第一條,這里小編給出一些安全建議,各位大佬權當參考:

1.?對于重要函數,建議使用一些防止重入的方法,如lock

2.合約代碼盡量滿足:Checks-Effects-Interaction模型

3.項目上線前應做好審計工作,并不斷迭代修改。審計方和項目方,是相互促進的關系。像本次事件中,審計中指出的錯誤,時隔一年被攻擊,豈不是很尷尬

4.應提前考慮好兼容問題,保證合約代碼的完備性。比如通縮/通脹代幣、ERC777代幣等比較特殊的代幣模型,都應盡可能的考慮與規避風險

參考

imBTCUniswapPoolDrainedfor~$300kinETH:?https://defirate.com/imbtc-uniswap-hack/

OpenzeppelinPoC:https://github.com/OpenZeppelin/exploit-uniswap#exploit-details

https://medium.com/imtoken/about-recent-uniswap-and-lendf-me-reentrancy-attacks-7cebe834cb3

詳解Uniswap的ERC777重入風險:https://paper.seebug.org/1182/

https://medium.com/imtoken/about-recent-uniswap-and-lendf-me-reentrancy-attacks-7cebe834cb3

Tags:ETHTOKENTOKETOKetheral代表什么意義GOV TokenRetire TokenLouie Duck Token

芝麻開門交易所
一文速覽 NFT 領域正在發生的 7 大趨勢_NFT:NFTS

撰文:ScottChipolina&AndrewHayward 編輯:南風 NFTs正以猛烈的勢頭復蘇.

1900/1/1 0:00:00
社交代幣悖論:新節點回報遞減_NFT:元宇宙

在這篇文章中,投資者GabyGoldberg討論了她所謂的“社交代幣悖論”——一個基于排他性的社交代幣社區中出現的問題.

1900/1/1 0:00:00
zkTube主網上線 以太坊跨Layer2從構想到達現實_TUB:TUBE2

據權威媒體Cointelegraph報道,以太坊跨Layer2協議zkTube于9月10日發布主網.

1900/1/1 0:00:00
OpenSea出現Bug導致42個NFT被毀,價值至少10萬美元_ENS:OPEN

金色財經報道,NFT市場OpenSea上的一個漏洞損毀了至少42件NFT,價值最少10萬美元。這個問題首先是由以太坊域名服務的首席開發者NickJohnson提出的,他指出,當他轉移一個ENS域.

1900/1/1 0:00:00
銀保監會周亮:金融違法犯罪得到嚴厲懲治_區塊鏈:比特幣市值走勢圖表

上證報中國證券網訊銀保監會副主席周亮9月4日在2021中國國際金融年度論壇上表示,今年以來,80%以上的經濟體通脹水平均在上升,全球核心通脹率升至多年最高水平;國際金融市場動蕩.

1900/1/1 0:00:00
區塊鏈+供應鏈金融:重塑中小企業信用體系_區塊鏈:數字貨幣和加密貨幣的區別在哪

黨的十八大以來,以習近平同志為核心的黨中央高度重視中小企業發展,“十四五”規劃和2035年遠景目標綱要更是提出“創新金融支持民營企業政策工具,健全融資增信支持體系”.

1900/1/1 0:00:00
ads