以太坊代理中的惡意後門

買賣虛擬貨幣
我們最近審查了Zeppelinos的初始版本,發現了代理模式中的一個漏洞,該模式用於實現幾乎所有可升級的智慧合約。此漏洞允許攻擊者隱藏惡意程式碼,如果不深入瞭解Solidity和Proxy Pattern的工作方式,很難發現惡意程式碼。這已在ZeppelinOS上修復。

Solidity函式呼叫internals

如果您是以太坊的開發人員,那麼您最有可能使用Solidity進行編寫和考慮如何設計智慧合約。

從網路的角度來看,智慧合約是一個與其相關聯的單個程式碼塊的帳戶。如果任何其他帳戶向合同傳送訊息,其程式碼將在EVM上執行。

那麼如果合約只有一段連續的程式碼,如何呼叫不同的函式呢?

以太坊定義了其元件之間通訊的標準方式,即應用程式二進位制介面或簡稱ABI。您可以將其視為低階API,不僅指定系統中可用的功能,還指定我們通常認為合理的工作量。其中一些是如何呼叫函式,如何傳遞引數以及它們如何返回值。

以太坊ABI規定您的事務的資料引數必須以函式選擇器開始,該函式選擇器標識您嘗試呼叫的方法。使用選擇器,合約的程式碼會跳轉到實現您嘗試呼叫的函式的部分。

函式選擇器只是函式簽名的sha3雜湊的前四個位元組。例如,get的選擇器計算為sha3(“get()”)[0:4],它給出了0x6d4ce63c。類似地,set的一個是sha3的結果(“set(uint256)”)[0:4]。

函式選擇器只有一個例外,這是因為在沒有選擇器的每個智慧合約中都存在一個回退函式。當沒有提供資料引數,或者給定的選擇器與契約的任何方法都不匹配時,它具有被呼叫的特殊行為。

重新審視代理模式

關於代理模式,它擁有多種變化和權衡模式。 無論您選擇哪種代理模式,其核心功能都是相同的:它將收到的所有訊息轉發給當前的合同實現。

我們來看看它是如何工作的。

你不需要理解裝配塊是如何工作的。它把當前訊息實現轉發並將接收到的資料引數傳送出去。

將轉發邏輯放在回退函式中,可以讓我們將任何呼叫轉發到代理中。事實證明,這種情況並不總是發生。

代理還需要它自己的元功能(meta-functionality),因為代理需要可升級性。因此,如果存在並且不執行回退功能,則不會轉發implementation()和proxyOwner()等函式。

代理選擇器衝突

您可能已經意識到代理智慧合約中的任何函式(其選擇器與應用智慧合約中的某個函式匹配)都將被直接呼叫,完全跳過應用碼。

因為函式選擇器使用固定數量的位元組,所以總是存在衝突的可能性。 這不是日常開發的問題,因為Solidity編譯器將檢測合同中的選擇器衝突,但是當選擇器用於交叉智慧合約互動時,這就變得可攻擊了。衝突可以被濫用來建立一個看似很好的合同,但實際上隱藏了一個後門。

在使用rust程式碼,我們發現clash550254402()與proxyOwner()具有相同的選擇器。 我們在Macbook Pro中可以很輕易能找到它。 但是駭客們可以利用該流程去尋找程式碼漏洞進行攻擊。

代理可利用性

代理模式是在以太坊生態系統中常見的智慧合約升級方法,選擇器衝突攻擊者可以使用它來獲取升級機制的訪問權攻擊或部署隱藏惡意功能的程式碼。

例如大多數可升級實現都有一些狀態遷移的概念,這是升級智慧合約的儲存功能。這些對於偽裝選擇器衝突特別有用,因為自動生成的字串(如commit number)可以作為這些函式的可接受名稱,從而使選擇器衝突攻擊易於隱藏。

在我們對ZeppelinOS進行的安全審計的背景下,我們發現這可以被任何人利用,而不僅僅是代理所有者,因為他們打算讓網路的任何使用者部署實現供其他使用者使用。另一個例子是,一個函式呼叫似乎可以轉移資金,從而實現竊取某人的資金,但實際上該函式根本不被呼叫。

解決方案

在我們發現此漏洞之前,Zeppelin的Francisco Giordano已經開始研究透明代理。這是一種改進的技術,旨在讓實現智慧合約使用與代理相同的函式名,而不會出現選擇器衝突,這就消除了攻擊。

新代理透過轉發任何函式呼叫來工作,只要它們不是來自代理所有者。但是衝突仍然存在,如果呼叫方不是代理所有者,則會轉發呼叫。這使得代理所有者成為唯一可能發生衝突的帳戶,因此使用者不會受到隱藏攻擊。

唯一的缺點是其他使用者將無法使用代理的ABI讀取代理的自身狀態(即所有者和實現)。他們將需要使用web3.eth.getstorageat()。這是一個相當小的代價,因為要確保可升級的合同完全按照其實現原始碼所顯示的方式執行。

總結

對於那些想更深入地瞭解如何利用這個漏洞的人,我們做了一個小練習。你的任務是試圖在合同中竊取ropsten-ETH
 https://ropsten.etherscan.io/address/0xb97dd0102bb67f81d25d686c661d7f0aed62e344,並弄清楚發生了什麼。 請記住,這是一個代理合同,所以你也應該看看它的實施。

你可以用這些合同做你想做的任何事情,只是不要完全清空它的餘額,這樣其他人也可以玩。

訊息是帳戶之間的通訊方式。當您傳送交易時,您正在向另一個帳戶傳送訊息。當傳送方是智慧合約時,它們通常稱為內部交易。

訊息實際上並不像傳統代理那樣轉發。所發生是在我們執行應用碼時,就好像它是透過delegatecall執行代理的程式碼一樣。

原作者:Patricio Palladino

免責聲明:

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

推荐阅读

;