慢霧:VETH 合約被黑分析

買賣虛擬貨幣
前言2020 年 7 月 1 日,VETH 合約遭遇駭客攻擊。慢霧安全團隊在收到情報後對本次攻擊事件進行了全面的分析,下面為大家就這次攻擊事件展開具體的技術分析。攻擊細節本次攻擊交易如下 0xdd1120a90ed4112b634266d6a244b93ca86785317bc75f0e170ab0cd97c65224

透過交易概覽可以看到攻擊者在 Uniswap 中使用 0.9 ETH 兌換成 VETH,然後使用 VETH 在 Vether 合約中進行操作,最終盜走鉅額的 VETH。

現在使用 OKO 合約瀏覽器對具體的攻擊細節進行分析(下圖只展示一部分)https://oko.palkeo.com/0xdd1120a90ed4112b634266d6a244b93ca86785317bc75f0e170ab0cd97c65224/

透過分析交易內具體的細節可以發現:攻擊者先建立了一個合約0x47Ed415006C6F8052Fff05fe983f31D6D24B8fDB 透過此合約對 Vether 合約中的 changeExcluded(unknown37217349) 函式與 transferFrom 函式進行了呼叫。

接下來對這兩個函式的具體程式碼進行分析:

function transferFrom(address from, address to, uint value) public override returns (bool success) {
        if(!mapAddress_Excluded[msg.sender]){
            require(value <= _allowances[from][msg.sender], 'Must not send more than allowance');
            _allowances[from][msg.sender] -= value;
        }
        _transfer(from, to, value);
        returntrue;
    }

可以看到在 transferFrom 函式中,先對 mapAddress_Excluded[msg.sender] 進行了 if 判斷,具體邏輯是mapAddress_Excluded[msg.sender]為 false 時,將會檢查對攻擊者合約的授權額度,然後呼叫_transfer函式進行轉賬。而這個邏輯顯然走不通,攻擊者合約是沒有任何授權額度的。因此mapAddress_Excluded[msg.sender]只能為 true ,然後直接呼叫_transfer函式進行轉賬。

接下來具體分析該如何將mapAddress_Excluded[msg.sender]設定為 true:

透過檢視合約可以發現:

合約在初始化時只將address(this)和burnAddress的mapAddress_Excluded置為 true,那麼可以肯定還有其他邏輯可以設定mapAddress_Excluded,透過分析  Vether 合約可以發現changeExcluded函式可以實現對mapAddress_Excluded的設定。

function changeExcluded(address excluded) external {    
        if(!mapAddress_Excluded[excluded]){
            _transfer(msg.sender, address(this), mapEra_Emission[1]/16);                    
            mapAddress_Excluded[excluded] = true;                                           
            excludedArray.push(excluded); excludedCount +=1;                                
            totalFees += mapEra_Emission[1]/16;                                             
            mapAddress_BlockChange[excluded] = block.number;                                
        } else {
            _transfer(msg.sender, address(this), mapEra_Emission[1]/32);                    
            mapAddress_Excluded[excluded] = false;                                          
            totalFees += mapEra_Emission[1]/32;                                            
            mapAddress_BlockChange[excluded] = block.number;                               
        }               
    }

透過分析changeExcluded函式可以發現其可見性為external,因此攻擊者合約可以直接呼叫changeExcluded函式,此時攻擊者合約的mapAddress_Excluded為 false,所以會進入 if 的邏輯中。

接下來對 if 邏輯內的程式碼進行具體分析:

在進行 if 邏輯後需要先支付手續費,具體為上方程式碼塊中的第 3 行,那這個手續費是從哪裡來呢?答案就是攻擊者最初轉入合約中的 0.9 ETH。

圖中可以看到,透過 0.9 ETH 兌換成約 138 VETH。

透過計算程式碼中的mapEra_Emission[1]/16我們可以得到攻擊者需要支付的手續費:我們讀取合約中的 mapEra_Emission可以知道 mapEra_Emission[1]為 2048。

此時計算mapEra_Emission[1]/16可得手續費為 2048/16 = 128 VETH,而攻擊者兌換了約138 VETH 是足夠用來支付手續費的,因此便可以透過上方程式碼塊中的第 4 行將攻擊者合約的mapAddress_Excluded置為 true。

完整的攻擊流程如下:

1. 建立攻擊合約,透過 Uniswap 將 0.9 ETH 兌換成約138 VETH(此處換幣為了後續支付手續費)
2. 呼叫 Vether 合約中的changeExcluded函式並利用先前在 Uniswap 兌換的約 138 VETH 支付 128 VETH 的手續費,然後將mapAddress_Excluded置為 true
3. 呼叫 transferFrom 函式,利用mapAddress_Excluded為 true,直接進行轉賬操作
4. 拿錢走人

駭客地址:
0xfa2700e67065bc364136b5e7f57112083cb2a0cd

攻擊交易:
0xdd1120a90ed4112b634266d6a244b93ca86785317bc75f0e170ab0cd97c65224

VETH 合約地址
0x75572098dc462f976127f59f8c97dfa291f81d8b

修復建議

此次攻擊主要利用 Vether 合約中changeExcluded函式的可見性為external且未有許可權限制,使用者可以直接進行外部呼叫為攻擊創造了必要的條件。因此應做好對changeExcluded函式的許可權或可見性的限制,從而避免任意使用者可以直接外部呼叫changeExcluded函式。

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读

;